50

I have an ImageView and I want to make it with rounded corners.

I use this:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> 
    <solid  android:color="@null"/>    

    <stroke android:width="1dp"
            android:color="#ff000000"/>


    <corners android:radius="62px"/> 
</shape>

And set this code as background of my imageview. It works, but the src image that I put on the ImageView is going out of the borders and doesn't adapt itself into the new shape.

How can I solve the problem?

Kaushik
  • 6,017
  • 5
  • 33
  • 51
BoraBora
  • 565
  • 1
  • 4
  • 9

12 Answers12

87

try this one :

public class CustomImageView extends ImageView {

    public static float radius = 18.0f;  

    public CustomImageView(Context context) {
        super(context);
    }

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

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

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

and

<your.pack.name.CustomImageView
                android:id="@+id/selectIcon"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:layout_centerInParent="true"
                android:scaleType="centerCrop" />

CustomImageView  iconImage = (CustomImageView )findViewById(R.id.selectIcon);
iconImage.setImageBitmap(bitmap);

or,

ImageView iv= new CustomImageView(this);
iv.setImageResource(R.drawable.pic);
MaxEcho
  • 13,325
  • 6
  • 72
  • 84
Anand
  • 2,865
  • 1
  • 16
  • 16
  • 1
    Thank you @Anand for sharing this, but I am not getting sharp edges for circle, would please!! guide me what would be radius for Image size is 40X40 dp. – swiftBoy Dec 03 '13 at 10:04
  • 1
    Note that in general you shouldn't make object allocations during draw or layout methods. It's fairly straightforward to move these allocations into other parts of the view object. – greg7gkb May 26 '14 at 23:38
  • @Salim, so is there any way to have only top left corner? – LiangWang May 30 '14 at 00:37
  • The best solution for me. Simple and clever. – Eliasz Kubala Nov 22 '14 at 15:53
  • hi it only works for me if i add myView.setLayerType(View.LAYER_TYPE_SOFTWARE, null). Any reason why it doesn't work otherwise? – iMDroid Nov 24 '14 at 09:56
  • 2
    Hmm.. But you should know that path clipping doesn't support anti-aliasing. See Romain Guy's comments on his post. "path clipping does not support antialiasing and you get jagged edges." http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/ – 김준호 Dec 14 '14 at 13:05
  • For me it works nicely with android version 5.0.1 but it doesn't work with 4.0.4. I figured already out that 4.0.4 doesn't support the canvas.clipPath function. Therefore I tried already [this post](http://stackoverflow.com/questions/8895677/work-around-canvas-clippath-that-is-not-supported-in-android-any-more) but it doesn't work for me... does anyone have an idea how to make it work? – Crazmiss Oct 11 '16 at 06:02
  • I used this class but corners are not smooth. Can you suggest what should I do to smooth the corners? – Vivek Pratap Singh Feb 13 '18 at 10:16
32

It's strange that nobody here has mentioned RoundedBitmapDrawable from Android Support Library v4. For me it is the simplest way to get rounded corners without borders. Here is example of usage:

RoundedBitmapDrawable roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(getResources(), bitmap);
final float roundPx = (float) bitmap.getWidth() * 0.06f;
roundedBitmapDrawable.setCornerRadius(roundPx);
lobzik
  • 10,427
  • 1
  • 25
  • 32
21

Make one function which make rounded to your bitmap using canvas.

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;
}

for more info:> here

Community
  • 1
  • 1
Ketan Ahir
  • 6,458
  • 1
  • 20
  • 43
  • This is neat! (Be sure to increase the pixel count considerably if it seems to not be working for you) – Sagar Jan 30 '21 at 18:18
  • I'm drawing bitmap on canvas along with shadow, for making shadow rounded this is my steps, `mPaint.setShadowLayer(radius, dX, dY, shadowColor);canvas.drawRoundRect(rect, cornerRadius, cornerRadius, mPaint);` and making bitmap corner rounded using your code but `shadow` and `bitmap` corners are differs from one-another, what should i do? – Vivek Thummar Apr 08 '21 at 06:30
9

The accepted answer uses path clipping, but it doesn't support anti-aliasing. See Romain Guy's comments on his post. "path clipping does not support antialiasing and you get jagged edges."

http://www.curious-creature.com/2012/12/11/android-recipe-1-image-with-rounded-corners/

There is one good library(vinc3m1’s RoundedImageView) that supoorts rounded corners on ImageView, but it only supports the same radiuses on every corners. So I made one that you can set different radiuses on each corners.

It doesn't rely on path clipping, nor redrawing. It only draws one time with canvas.drawPath() method. So I finally got result that I wanted like below.

enter image description here

See : https://github.com/pungrue26/SelectableRoundedImageView

김준호
  • 14,557
  • 7
  • 39
  • 35
5

If you need border also then: 1. You can use a rounded box image with a transparent body and white from outside. For Example:

Rounded box

and use this with target image like below:

<FrameLayout
android:layout_width="100px"
android:layout_height="100px" >
<ImageView
        android:id="@+id/targetImage"
        android:layout_width="100px"
        android:layout_height="100px"
        android:src="@drawable/app_icon"
        android:layout_gravity="center" />
<ImageView
        android:id="@+id/boxImage"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:scaleType="fitXY"
        android:src="@drawable/box" />

  1. Adding CardView as parent layout of ImageView also be a good solution.
Kalu Khan Luhar
  • 1,048
  • 1
  • 21
  • 32
5

If you need make Bitmap with different corner radii and I recommend follow code:

private static Bitmap createRoundedRectBitmap(@NonNull Bitmap bitmap,
                                float topLeftCorner, float topRightCorner,
                                float bottomRightCorner, float bottomLeftCorner) {
    Bitmap output = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), 
                                        Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(output);

    final int color = Color.WHITE;
    final Paint paint = new Paint();
    final Rect rect = new Rect(0, 0, bitmap.getWidth(), bitmap.getHeight());
    final RectF rectF = new RectF(rect);
    Path path = new Path();
    float[] radii = new float[]{
            topLeftCorner, bottomLeftCorner,
            topRightCorner, topRightCorner,
            bottomRightCorner, bottomRightCorner,
            bottomLeftCorner, bottomLeftCorner
    };

    paint.setAntiAlias(true);
    canvas.drawARGB(0, 0, 0, 0);
    paint.setColor(color);
    path.addRoundRect(rectF, radii, Path.Direction.CW);
    canvas.drawPath(path, paint);
    paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC_IN));
    canvas.drawBitmap(bitmap, rect, rect, paint);
    return output;
}
Sergei Vasilenko
  • 2,183
  • 2
  • 25
  • 37
  • The second element should be topLeftCorner rather than bottomLeftCorner, then it works. – Saint Dec 09 '20 at 06:42
4

For me, the below method does the magic. :) This method accepts a bitmap object and returns it back with rounded corners. roundPx is the number of rounded pixels you want:

public static Bitmap getRoundedCornerBitmap(Bitmap bitmap) {
    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 = 12;

    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;
}

...or you could use this library instead of ImageView without any further coding.

Niamatullah Bakhshi
  • 1,336
  • 12
  • 22
3

It can be done with background drawable, like explain in many posts including this one, but it also needs to set clipping. Here a full example:

The code:

AppCompatImageView iconView = findViewById(R.id.thumbnail);
iconView.setClipToOutline(true);

The layout:

<android.support.v7.widget.AppCompatImageView
    android:id="@+id/thumbnail"
    android:layout_width="80dp"
    android:layout_height="80dp"
    android:contentDescription="@string/thumbnail"
    android:scaleType="centerInside"
    android:background="@drawable/round_view" <!--here set the drawable as background -->
    tools:src="@mipmap/ic_user" />

The drawable:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle">
    <corners android:radius="10dp" />
</shape>
MiguelSlv
  • 9,553
  • 7
  • 72
  • 127
0
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 defStyle) {
        super(context, attrs, defStyle);
    }

    @Override
    protected void onDraw(Canvas canvas) {

        super.onDraw(canvas);

        Bitmap rounder = Bitmap.createBitmap(getWidth(),getHeight(),Bitmap.Config.ARGB_8888);
        Canvas canvasRound = new Canvas(rounder);    

        Paint xferPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        xferPaint.setColor(Color.BLACK);

        final int rx = this.getWidth(); //our x radius
        final int ry = this.getHeight(); //our y radius

        canvasRound.drawRoundRect(new RectF(0,0,rx,ry), rx, ry, xferPaint);     

        xferPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));

        canvas.drawBitmap(rounder, 0, 0, xferPaint);

    }

}
0
/**
 * Creates new circular bitmap based on original one.
 * @param newCornerRadius is optional
 */
fun Bitmap.toCircular(context: Context, newCornerRadius: Float? = null): RoundedBitmapDrawable {
    return RoundedBitmapDrawableFactory.create(context.resources, this).apply {
        isCircular = true
        newCornerRadius?.let {
            cornerRadius = it
        }
    }
}
Sergei Maleev
  • 189
  • 1
  • 3
-2

The method to make rounded corners for imageview in android is not rocket science guys! just use a png with required curves with the same color as your background and set the overlay to FITXY.!

-4
public void drawRoundImage(boolean isEditPicEnable){
   if(originalImageBitmap != null){
        setBackgroundResource(R.drawable.ic_account_user_outer_circle_blue);

        if (isEditPicEnable) {
            setBackgroundResource(R.drawable.ic_account_user_outer_circle_white);
            Bitmap mask = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_white_mask);
            Bitmap mask1 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_pencil_bg);
            originalImageBitmap = Bitmap.createScaledBitmap(originalImageBitmap, mask.getWidth(), mask.getHeight(), true);
            Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(), Bitmap.Config.ARGB_8888);
            Canvas mCanvas = new Canvas(result);
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mCanvas.drawBitmap(originalImageBitmap, 0, 0, null);
            mCanvas.drawBitmap(mask, 0, 0, paint);
            mCanvas.drawBitmap(mask1, 0, 0, null);
            Bitmap mask2 = BitmapFactory.decodeResource(getResources(), R.drawable.ic_account_pencil);
            mCanvas.drawBitmap(mask2, 0, 0, null);
            setImageBitmap(result);
            setScaleType(ScaleType.FIT_XY);
        } else {
            Bitmap mask = BitmapFactory.decodeResource(getResources(),R.drawable.ic_account_white_mask);
            originalImageBitmap = Bitmap.createScaledBitmap(originalImageBitmap, mask.getWidth(),mask.getHeight(), true);
            Bitmap result = Bitmap.createBitmap(mask.getWidth(), mask.getHeight(),Bitmap.Config.ARGB_8888);
            Canvas mCanvas = new Canvas(result);
            Paint paint = new Paint(Paint.ANTI_ALIAS_FLAG);
            paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_IN));
            mCanvas.drawBitmap(originalImageBitmap, 0, 0, null);
            mCanvas.drawBitmap(mask, 0, 0, paint);
            paint.setXfermode(null);
            setImageBitmap(result);
            setScaleType(ScaleType.FIT_XY);
        }

    }else{
        setBackgroundResource(R.drawable.ic_account_user_outer_circle_blue);
        setImageResource(R.drawable.my_ac_default_profile_pic);
    }

}
Prashant
  • 17
  • 5
  • 1
    While this answer *may* solve the question that was posted, it is recommended that you add some human-readable text too that explains what the code does or where it is different from the OP's code. As it is now, it's just a code-dump that doesn't even explain why this is any good. – Oliver W. Jan 28 '15 at 19:30