android - गोलाकार कोनों के साथ एक छवि दृश्य कैसे बनाएँ?




imageview android-imageview (20)

एंड्रॉइड में, एक ImageView डिफ़ॉल्ट रूप से एक आयताकार है। ImageView में मैं इसे गोलाकार आयत (मेरे बिटमैप के सभी 4 कोनों को गोलाकार आयत के रूप में बंद कर सकता हूं) कैसे बना सकता हूं?


आपको ImageView विस्तार करना चाहिए और अपना स्वयं का गोलाकार आयत बनाना चाहिए।

यदि आप छवि के चारों ओर एक फ्रेम चाहते हैं तो आप लेआउट में छवि दृश्य के शीर्ष पर गोलाकार फ्रेम को भी अतिरंजित कर सकते हैं।

[संपादित करें] उदाहरण के लिए FrameLayout का उपयोग करके, मूल छवि को ऑप करने के लिए फ्रेम को सुपरमिशन करें। FrameLayout का पहला तत्व वह FrameLayout होगी जिसे आप गोलाकार करना चाहते हैं। फिर फ्रेम के साथ एक और ImageView जोड़ें। दूसरा ImageView मूल ImageView शीर्ष पर प्रदर्शित किया जाएगा और इस प्रकार एंड्रॉइड ऑर्गेनिक ImageView ऊपर इसकी सामग्री को आकर्षित करेगा।


उपर्युक्त उत्तर काम करते समय, रोमैन गाय (एक कोर एंड्रॉइड डेवलपर) अपने ब्लॉग में एक बेहतर तरीका दिखाता है जो बिटमैप की एक प्रति नहीं बनाते हुए शेडर का उपयोग करके कम स्मृति का उपयोग करता है। कार्यक्षमता का सामान्य सारांश यहां है:

BitmapShader shader;
shader = new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);

Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(shader);

RectF rect = new RectF(0.0f, 0.0f, width, height);

// rect contains the bounds of the shape
// radius is the radius in pixels of the rounded corners
// paint contains the shader that will texture the shape
canvas.drawRoundRect(rect, radius, radius, paint);

अन्य तरीकों से इसका लाभ यह है कि यह:

  • बिटमैप की एक अलग प्रति नहीं बनाता है, जो बड़ी छवियों के साथ बहुत सारी मेमोरी का उपयोग करता है [बनाम अन्य उत्तरों के अधिकांश]
  • एंटीअलाइजिंग का समर्थन करता है [बनाम क्लिपपैथ विधि]
  • अल्फा का समर्थन करता है [बनाम xfermode + पोर्टरडफ विधि]
  • हार्डवेयर त्वरण का समर्थन करता है [बनाम क्लिपपैथ विधि]
  • केवल कैनवास में एक बार खींचता है [बनाम xfermode और clippath विधियों]

मैंने इस कोड के आधार पर एक RoundedImageView बनाया है जो इस तर्क को एक छवि ScaleType में लपेटता है और उचित ScaleType समर्थन और वैकल्पिक गोलाकार सीमा जोड़ता है।


एक और आसान तरीका है कोने त्रिज्या के साथ कार्डव्यू का उपयोग करना और एक छवि दृश्य अंदर:

  <android.support.v7.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            app:cardCornerRadius="8dp"
            android:layout_margin="5dp"
            android:elevation="10dp">

            <ImageView
                android:id="@+id/roundedImageView"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:src="@drawable/image"
                android:background="@color/white"
                android:scaleType="centerCrop"
                />
        </android.support.v7.widget.CardView>


एपीआई 21 में View क्लास में गोल आकार के लिए क्लिपिंग को जोड़ा गया था।

बस यह करो:

  • एक गोलाकार आकार खींचने योग्य बनाएं, इस तरह कुछ:

रेस / drawable / round_outline.xml

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
    ...
</shape>
  • अपनी छवि android:background="@drawable/round_outline" की पृष्ठभूमि के रूप में android:background="@drawable/round_outline" सेट करें: android:background="@drawable/round_outline"
  • इस documentation अनुसार, आपको बस इतना करना है कि android:clipToOutline="true" जोड़ें android:clipToOutline="true"

दुर्भाग्यवश, एक बग है और वह XML विशेषता पहचान नहीं है। सौभाग्य से, हम अभी भी जावा में क्लिपिंग सेट कर सकते हैं:

  • आपकी गतिविधि या खंड में: ImageView.setClipToOutline(true)

यहां यह कैसा दिखाई देगा:

ध्यान दें:

यह विधि किसी भी खींचने योग्य आकार के लिए काम करती है (न केवल गोलाकार)। यह ImageView को आपके Drawable xml में परिभाषित किए गए आकार की रूपरेखा पर क्लिप करेगा।

ImageViews के बारे में विशेष नोट

setClipToOutline() केवल तभी काम करता है जब दृश्य की पृष्ठभूमि को आकार देने योग्य आकार पर सेट किया जाता है। यदि यह पृष्ठभूमि आकार मौजूद है, तो देखें क्लिपिंग और छायांकन उद्देश्यों के लिए सीमाओं के रूप में आकार की रूपरेखा का व्यवहार करता है।

इसका अर्थ यह है कि, यदि आप ImageView पर कोनों को setClipToOutline() लिए setClipToOutline() का उपयोग करना चाहते हैं, तो आपकी छवि android:src बजाय android:src का उपयोग करके सेट की जानी चाहिए android:background (क्योंकि पृष्ठभूमि को आपके गोलाकार आकार में सेट किया जाना चाहिए)। यदि आपको src की बजाय अपनी छवि सेट करने के लिए पृष्ठभूमि का उपयोग करना होगा, तो आप इस वर्कअराउंड का उपयोग कर सकते हैं:

  • एक लेआउट बनाएं और अपनी पृष्ठभूमि को अपने आकार में खींचने योग्य बनाएं
  • अपने ImageView के चारों ओर उस लेआउट को लपेटें (बिना पैडिंग के)
  • ImageView (लेआउट में किसी और चीज सहित) अब गोलाकार लेआउट आकार के साथ प्रदर्शित होगा।

चूंकि सभी उत्तरों मेरे लिए बहुत जटिल लगते थे, सिर्फ गोल कोनों के लिए मैंने सोचा और एक और समाधान में आया जो मुझे लगता है कि साझा करने के लायक है, बस एक्सएमएल के साथ यदि आपके पास छवि के चारों ओर कुछ जगह है:

इस तरह पारदर्शी सामग्री के साथ एक सीमाबद्ध आकार बनाएँ:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners 
        android:radius="30dp" />
    <stroke 
        android:color="#ffffffff"
        android:width="10dp" />
</shape> 

फिर एक रिलेवेटिवआउट में आप अपनी छवि को पहले और फिर किसी अन्य छवि दृश्य के साथ आकार के ऊपर एक ही स्थान पर रख सकते हैं। कवर चौड़ाई सीमा चौड़ाई की मात्रा से आकार में बड़ा होना चाहिए। बाहरी त्रिज्या को परिभाषित करने के रूप में एक बड़ा कोने त्रिज्या लेने के लिए सावधान रहें, लेकिन आंतरिक त्रिज्या आपकी छवि को कवर करती है।

उम्मीद है कि यह किसी की भी मदद करता है।

सीक्यूएम अनुरोध के अनुसार सापेक्ष लेआउट उदाहरण के रूप में संपादित करें :

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent" >

    <ImageView
        android:id="@+id/imageToShow"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignBottom="@+id/imgCorners"
        android:layout_alignLeft="@+id/imgCorners"
        android:layout_alignRight="@+id/imgCorners"
        android:layout_alignTop="@+id/imgCorners"
        android:background="#ffffff"
        android:contentDescription="@string/desc"
        android:padding="5dp"
        android:scaleType="centerCrop" />

    <ImageView
        android:id="@+id/imgCorners"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:adjustViewBounds="true"
        android:contentDescription="@string/desc"
        android:src="@drawable/corners_white" />

</RelativeLayout>

मैंने कस्टम छवि दृश्य द्वारा किया है:

public class RoundRectCornerImageView extends ImageView {

    private float radius = 18.0f;
    private Path path;
    private RectF rect;

    public RoundRectCornerImageView(Context context) {
        super(context);
        init();
    }

    public RoundRectCornerImageView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    public RoundRectCornerImageView(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
        init();
    }

    private void init() {
        path = new Path();

    }

    @Override
    protected void onDraw(Canvas canvas) {
        rect = new RectF(0, 0, this.getWidth(), this.getHeight());
        path.addRoundRect(rect, radius, radius, Path.Direction.CW);
        canvas.clipPath(path);
        super.onDraw(canvas);
    }
}

कैसे इस्तेमाल करे:

<com.mypackage.RoundRectCornerImageView
     android:id="@+id/imageView"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:scaleType="fitXY" />

आउटपुट:

उम्मीद है कि यह आपकी मदद करेगा।


यह प्रतिक्रिया में बहुत देर हो चुकी है, लेकिन किसी और के लिए जो इसकी तलाश में है, आप अपनी छवियों के कोनों को मैन्युअल रूप से गोल करने के लिए निम्न कोड कर सकते हैं।

http://www.ruibm.com/?p=184

यह मेरा कोड नहीं है, लेकिन मैंने इसका इस्तेमाल किया है और यह अद्भुत काम करता है। मैंने इसे इमेजहेल्पर क्लास के भीतर एक सहायक के रूप में इस्तेमाल किया और इसे किसी दिए गए चित्र के लिए आवश्यक पंख की मात्रा में पास करने के लिए थोड़ा सा विस्तार किया।

अंतिम कोड इस तरह दिखता है:

package com.company.app.utils;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Bitmap.Config;
import android.graphics.PorterDuff.Mode;

public class ImageHelper {
    public static Bitmap getRoundedCornerBitmap(Bitmap bitmap, int pixels) {
        Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap
                .getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);

        final int color = 0xff424242;
        final Paint paint = new Paint();
        final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
        final RectF rectF = new RectF(rect);
        final float roundPx = pixels;

        paint.setAntiAlias(true);
        canvas.drawARGB(0, 0, 0, 0);
        paint.setColor(color);
        canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

        paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
        canvas.drawBitmap(bitmap, rect, rect, paint);

        return output;
    }
}

उम्मीद है कि यह किसी की मदद करता है!


रोमैन गाय वह जगह है जहां यह है।

निम्नानुसार न्यूनतम संस्करण।

Bitmap bitmap = ((BitmapDrawable) getResources().getDrawable(R.drawable.image)).getBitmap();

Bitmap bitmapRounded = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), bitmap.getConfig());
Canvas canvas = new Canvas(bitmapRounded);
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setShader(new BitmapShader(bitmap, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));
canvas.drawRoundRect((new RectF(0.0f, 0.0f, bitmap.getWidth(), bitmap.getHeight())), 10, 10, paint);

imageView.setImageBitmap(bitmapRounded);

here छवि ImageLoader here उपयोग कर ImageLoader छवि

DisplayImageOptions बनाएं:

DisplayImageOptions options = new DisplayImageOptions.Builder()
    // this will make circle, pass the width of image 
    .displayer(new RoundedBitmapDisplayer(getResources().getDimensionPixelSize(R.dimen.image_dimen_menu))) 
    .cacheOnDisc(true)
    .build();

imageLoader.displayImage(url_for_image,ImageView,options);

या आप स्क्वायर से उपयोगकर्ता Picasso लाइब्रेरी कर सकते हैं।

Picasso.with(mContext)
    .load(com.app.utility.Constants.BASE_URL+b.image)
    .placeholder(R.drawable.profile)
    .error(R.drawable.profile)
    .transform(new RoundedTransformation(50, 4))
    .resizeDimen(R.dimen.list_detail_image_size, R.dimen.list_detail_image_size)
    .centerCrop()
    .into(v.im_user);

आप यहाँ here RoundedTransformation फ़ाइल डाउनलोड कर सकते here


निम्नलिखित गोलाकार आयताकार लेआउट ऑब्जेक्ट बनाता है जो उसमें रखे गए किसी भी बच्चे की वस्तुओं के चारों ओर एक गोलाकार आयत खींचता है। यह भी दिखाता है कि लेआउट xml फ़ाइलों का उपयोग किए बिना प्रोग्रामेटिक रूप से दृश्य और लेआउट कैसे बनाएं।

package android.example;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;
import android.widget.TextView;

public class MessageScreen extends Activity {
 /** Called when the activity is first created. */
 @Override
 public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  int mainBackgroundColor = Color.parseColor("#2E8B57");
  int labelTextColor = Color.parseColor("#FF4500");
  int messageBackgroundColor = Color.parseColor("#3300FF");
  int messageTextColor = Color.parseColor("#FFFF00");

  DisplayMetrics metrics = new DisplayMetrics();
  getWindowManager().getDefaultDisplay().getMetrics(metrics);
  float density = metrics.density;
  int minMarginSize = Math.round(density * 8);
  int paddingSize = minMarginSize * 2;
  int maxMarginSize = minMarginSize * 4;

  TextView label = new TextView(this);
  /*
   * The LayoutParams are instructions to the Layout that will contain the
   * View for laying out the View, so you need to use the LayoutParams of
   * the Layout that will contain the View.
   */
  LinearLayout.LayoutParams labelLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT);
  label.setLayoutParams(labelLayoutParams);
  label.setTextSize(TypedValue.COMPLEX_UNIT_SP, 18);
  label.setPadding(paddingSize, paddingSize, paddingSize, paddingSize);
  label.setText(R.string.title);
  label.setTextColor(labelTextColor);

  TextView message = new TextView(this);
  RoundedRectangle.LayoutParams messageLayoutParams = new RoundedRectangle.LayoutParams(
 LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This tells the RoundedRectangle to put some extra space around the
   * View.
   */
  messageLayoutParams.setMargins(minMarginSize, paddingSize,
    minMarginSize, maxMarginSize);
  message.setLayoutParams(messageLayoutParams);
  message.setTextSize(TypedValue.COMPLEX_UNIT_SP, paddingSize);
  message.setText(R.string.message);
  message.setTextColor(messageTextColor);
  message.setBackgroundColor(messageBackgroundColor);

  RoundedRectangle messageContainer = new RoundedRectangle(this);
  LinearLayout.LayoutParams messageContainerLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  messageContainerLayoutParams.setMargins(paddingSize, 0, paddingSize, 0);
  messageContainer.setLayoutParams(messageContainerLayoutParams);
  messageContainer.setOrientation(LinearLayout.VERTICAL);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This tells the RoundedRectangle to color the the exta space that was
   * put around the View as well as the View. This is exterior color of
   * the RoundedRectangle.
   */
  messageContainer.setBackgroundColor(mainBackgroundColor);
  /*
   * This is one of the calls must made to force a ViewGroup to call its
   * draw method instead of just calling the draw method of its children.
   * This is the interior color of the RoundedRectangle. It must be
   * different than the exterior color of the RoundedRectangle or the
   * RoundedRectangle will not call its draw method.
   */
  messageContainer.setInteriorColor(messageBackgroundColor);
  // Add the message to the RoundedRectangle.
  messageContainer.addView(message);

  //
  LinearLayout main = new LinearLayout(this);
  LinearLayout.LayoutParams mainLayoutParams = new LinearLayout.LayoutParams(
    LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT);
  main.setLayoutParams(mainLayoutParams);
  main.setOrientation(LinearLayout.VERTICAL);
  main.setBackgroundColor(mainBackgroundColor);
  main.addView(label);
  main.addView(messageContainer);

  setContentView(main);
 }
}

RoundedRectangle लेआउट ऑब्जेक्ट के लिए क्लास यहां परिभाषित किया गया है:

/**
 *  A LinearLayout that draws a rounded rectangle around the child View that was added to it.
 */
package android.example;

import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.widget.LinearLayout;

/**
 * A LinearLayout that has rounded corners instead of square corners.
 * 
 * @author Danny Remington
 * 
 * @see LinearLayout
 * 
 */
public class RoundedRectangle extends LinearLayout {
 private int mInteriorColor;

 public RoundedRectangle(Context p_context) {
  super(p_context);
 }

 public RoundedRectangle(Context p_context, AttributeSet attributeSet) {
  super(p_context, attributeSet);
 }

 // Listener for the onDraw event that occurs when the Layout is drawn.
 protected void onDraw(Canvas canvas) {
  Rect rect = new Rect(0, 0, getWidth(), getHeight());
  RectF rectF = new RectF(rect);
  DisplayMetrics metrics = new DisplayMetrics();
  Activity activity = (Activity) getContext();
  activity.getWindowManager().getDefaultDisplay().getMetrics(metrics);
  float density = metrics.density;
  int arcSize = Math.round(density * 10);

  Paint paint = new Paint();
  paint.setColor(mInteriorColor);

  canvas.drawRoundRect(rectF, arcSize, arcSize, paint);
 }

 /**
  * Set the background color to use inside the RoundedRectangle.
  * 
  * @param Primitive int - The color inside the rounded rectangle.
  */
 public void setInteriorColor(int interiorColor) {
  mInteriorColor = interiorColor;
 }

 /**
  * Get the background color used inside the RoundedRectangle.
  * 
  * @return Primitive int - The color inside the rounded rectangle.
  */
 public int getInteriorColor() {
  return mInteriorColor;
 }

}

Apply a shape to your imageView as below:

<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle" >
    <solid android:color="#faf5e6" />
    <stroke
        android:width="1dp"
        android:color="#808080" />
    <corners android:radius="15dp" />
    <padding
        android:bottom="5dp"
        android:left="5dp"
        android:right="5dp"
        android:top="5dp" />
</shape>

it may be helpful to you friend.


Here is a simple example overriding imageView, you can then also use it in layout designer to preview.

public class RoundedImageView extends ImageView {
public RoundedImageView(Context context) {
    super(context);
}

public RoundedImageView(Context context, AttributeSet attrs) {
    super(context, attrs);
}

public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

@TargetApi(Build.VERSION_CODES.LOLLIPOP)
public RoundedImageView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
    super(context, attrs, defStyleAttr, defStyleRes);
}

@Override
public void setImageDrawable(Drawable drawable) {
    float radius = 0.1f;
    Bitmap bitmap = ((BitmapDrawable) drawable).getBitmap();
    RoundedBitmapDrawable rid = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
    rid.setCornerRadius(bitmap.getWidth() * radius);
    super.setImageDrawable(rid);
}

}

This is for fast solution. Radius is used on all corners and is based of percentage of bitmap width.

I just overrided setImageDrawable and used support v4 method for rounded bitmap drawable.

उपयोग:

<com.example.widgets.RoundedImageView
        android:layout_width="39dp"
        android:layout_height="39dp"
        android:src="@drawable/your_drawable" />

Preview with imageView and custom imageView:


If you are using Glide Library this would be helpful:

Glide.with(getApplicationContext())
     .load(image_url)
     .asBitmap()
     .centerCrop()
     .into(new BitmapImageViewTarget(imageView) {
        @Override
        protected void setResource(Bitmap resource) {
          RoundedBitmapDrawable circularBitmapDrawable =
                       RoundedBitmapDrawableFactory.create(getApplicationContext().getResources(), resource);
          circularBitmapDrawable.setCornerRadius(dpToPx(10));
          circularBitmapDrawable.setAntiAlias(true);
          imageView.setImageDrawable(circularBitmapDrawable);
        }
     });


public int dpToPx(int dp) {
  DisplayMetrics displayMetrics = getApplicationContext().getResources().getDisplayMetrics();
  return Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT));
}

If you're looking for a fast but dirty solution you can use RoundedImageView by Vincent Mi.


Thanks a lot to first answer. Here is modified version to convert a rectangular image into a square one (and rounded) and fill color is being passed as parameter.

public static Bitmap getRoundedBitmap(Bitmap bitmap, int pixels, int color) {

    Bitmap inpBitmap = bitmap;
    int width = 0;
    int height = 0;
    width = inpBitmap.getWidth();
    height = inpBitmap.getHeight();

    if (width <= height) {
        height = width;
    } else {
        width = height;
    }

    Bitmap output = Bitmap.createBitmap(width, height, Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, width, height);
    final RectF rectF = new RectF(rect);
    final float roundPx = pixels;

    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    canvas.drawRoundRect(rectF, roundPx, roundPx, paint);

    paint.setXfermode(new PorterDuffXfermode(Mode.SRC_IN));
    canvas.drawBitmap(inpBitmap, rect, rect, paint);

    return output;
}

This isn't exactly the answer, but it's a solution that is similar. It may help people who were in the same boat as I was.

My image, an application logo, had a transparent background, and I was applying an XML gradient as the image background. I added the necessary padding/margins to the imageView in XML, then added this as my background:

<?xml version="1.0" encoding="utf-8"?>

<item>

    <shape>

        <gradient
            android:type="linear"
            android:startColor="@color/app_color_light_background"
            android:endColor="@color/app_color_disabled"
            android:angle="90"
        />

        <!-- Round the top corners. -->
        <corners
            android:topLeftRadius="@dimen/radius_small"
            android:topRightRadius="@dimen/radius_small"
        />

    </shape>

</item>


Use this to get circular image with border-

    public static Bitmap getCircularBitmapWithBorder(Bitmap bitmap, int bordercolor) {
    if (bitmap == null || bitmap.isRecycled()) {
        return null;
    }
    int borderWidth=(int)(bitmap.getWidth()/40);
    final int width = bitmap.getWidth() + borderWidth;
    final int height = bitmap.getHeight() + borderWidth;

    Bitmap canvasBitmap = Bitmap.createBitmap(width, height,
            Bitmap.Config.ARGB_8888);
    BitmapShader shader = new BitmapShader(bitmap, TileMode.CLAMP,
            TileMode.CLAMP);
    Paint paint = new Paint();
    paint.setAntiAlias(true);
    paint.setShader(shader);

    Canvas canvas = new Canvas(canvasBitmap);
    float radius = width > height ? ((float) height) / 2f
            : ((float) width) / 2f;
    canvas.drawCircle(width / 2, height / 2, radius, paint);
    paint.setShader(null);
    paint.setStyle(Paint.Style.STROKE);
    paint.setColor(bordercolor);
    paint.setStrokeWidth(borderWidth);
    canvas.drawCircle(width / 2, height / 2, radius - borderWidth / 2,
            paint);
    return canvasBitmap;
}

With the help of glide library and RoundedBitmapDrawableFactory class it's easy to achieve. You may need to create circular placeholder image.

    Glide.with(context)
        .load(imgUrl)
        .asBitmap()
        .placeholder(R.drawable.placeholder)
        .error(R.drawable.placeholder)
        .into(new BitmapImageViewTarget(imgProfilePicture) {
            @Override
            protected void setResource(Bitmap resource) {
                RoundedBitmapDrawable drawable = RoundedBitmapDrawableFactory.create(context.getResources(),
                        Bitmap.createScaledBitmap(resource, 50, 50, false));
                drawable.setCornerRadius(10); //drawable.setCircular(true);
                imgProfilePicture.setImageDrawable(drawable);
            }
        });

if your image is on internet the best way is using glide and RoundedBitmapDrawableFactory (from API 21 - but available in support library) like so:

 Glide.with(ctx).load(url).asBitmap().centerCrop().into(new BitmapImageViewTarget(imageView) {
    @Override
    protected void setResource(Bitmap res) {
        RoundedBitmapDrawable bitmapDrawable =
             RoundedBitmapDrawableFactory.create(ctx.getResources(), res);
        bitmapDrawable.setCircular(true);//comment this line and uncomment the next line if you dont want it fully cricular
        //circularBitmapDrawable.setCornerRadius(cornerRadius);
        imageView.setImageDrawable(bitmapDrawable);
    }
});

why not do clipping in draw()?

Here is my solution:

  • extend RelativeLayout with clipping
  • put ImageView (or other views) into the layout:

code:

public class RoundRelativeLayout extends RelativeLayout {

private final float radius;

public RoundRelativeLayout(Context context, AttributeSet attrs) {
    super(context, attrs);

    TypedArray attrArray = context.obtainStyledAttributes(attrs,
            R.styleable.RoundRelativeLayout);
    radius = attrArray.getDimension(
            R.styleable.RoundRelativeLayout_radius, 0);
}

private boolean isPathValid;
private final Path path = new Path();

private Path getRoundRectPath() {
    if (isPathValid) {
        return path;
    }

    path.reset();

    int width = getWidth();
    int height = getHeight();
    RectF bounds = new RectF(0, 0, width, height);

    path.addRoundRect(bounds, radius, radius, Direction.CCW);
    isPathValid = true;
    return path;
}

@Override
protected void dispatchDraw(Canvas canvas) {
    canvas.clipPath(getRoundRectPath());
    super.dispatchDraw(canvas);
}

@Override
public void draw(Canvas canvas) {
    canvas.clipPath(getRoundRectPath());
    super.draw(canvas);
}

@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

    int oldWidth = getMeasuredWidth();
    int oldHeight = getMeasuredHeight();
    super.onMeasure(widthMeasureSpec, heightMeasureSpec);

    int newWidth = getMeasuredWidth();
    int newHeight = getMeasuredHeight();
    if (newWidth != oldWidth || newHeight != oldHeight) {
        isPathValid = false;
    }
}
}




rounded-corners