Android Round Corner ImageView

Making round corners on the image by using a mask Put an ImageView and a mask view in a RelativeLayout. Make the mask view round corners and put it on top of the ImageView.

The layout:

<RelativeLayout
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:background="#1b81d4">
    <ImageView
        android:id="@+id/image1"
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:padding="10dp"
        android:scaleType="fitXY"
        android:src="@drawable/fire" />

    <View
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/round_corners_mask" />
</RelativeLayout>

The drawable round_corners_mask.xml

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

Apply round corner image transformation when loading the image through Picasso.
The round corner transformation class. RoundCornersTransformation.java

import android.graphics.Bitmap;
import android.graphics.Bitmap.Config;
import android.graphics.BitmapShader;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.Shader;


// enables hardware accelerated rounded corners
// original idea here : http://www.curious-creature.org/2012/12/11/android-recipe-1-image-with-rounded-corners/
// https://gist.github.com/aprock/6213395
// https://gist.github.com/amardeshbd/06b491d4adb568b1b226a20d4953a180
public class RoundCornersTransformation implements com.squareup.picasso.Transformation {
    private final int radius;  // dp
    private final int margin;  // dp
    private String KEY = "";
    private boolean topCorners = true;
    private boolean bottomCorners = true;

    /**
     * Creates rounded transformation for all corners.
     *
     * @param radius radius is corner radii in dp
     * @param margin margin is the board in dp
     */
    public RoundCornersTransformation(final int radius, final int margin) {
        this.radius = radius;
        this.margin = margin;
        if (KEY.isEmpty()) KEY = "rounded_" + radius + margin;
    }


    /**
     * Creates rounded transformation for top or bottom corners.
     *
     * @param radius radius is corner radii in dp
     * @param margin margin is the board in dp
     * @param topCornersOnly Rounded corner for top corners only.
     * @param bottomCornersOnly Rounded corner for bottom corners only.
     */
    public RoundCornersTransformation(final int radius, final int margin, boolean topCornersOnly,
                                      boolean bottomCornersOnly) {
        this(radius, margin);
        topCorners = topCornersOnly;
        bottomCorners = bottomCornersOnly;
        KEY = "rounded_" + radius + margin + topCorners + bottomCorners;
    }

    @Override
    public Bitmap transform(final Bitmap source) {
        final Paint paint = new Paint();
        paint.setAntiAlias(true);
        paint.setShader(new BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP));

        Bitmap output = Bitmap.createBitmap(source.getWidth(), source.getHeight(), Config.ARGB_8888);
        Canvas canvas = new Canvas(output);
        if(topCorners && bottomCorners) {
            // Uses native method to draw symmetric rounded corners
            canvas.drawRoundRect(new RectF(margin, margin, source.getWidth() - margin,
                    source.getHeight() - margin), radius, radius, paint);
        } else {
            // Uses custom path to generate rounded corner individually
            canvas.drawPath(RoundedRect(margin, margin, source.getWidth() - margin,
                    source.getHeight() - margin, radius, radius, topCorners, topCorners,
                    bottomCorners, bottomCorners), paint);
        }


        if (source != output) {
            source.recycle();
        }

        return output;
    }


    @Override
    public String key() {
        return "rounded_" + radius + margin;
//        return KEY;
    }

    /**
     * Prepares a path for rounded corner selectively.
     * Source taken from http://stackoverflow.com/a/35668889/6635889
     * @param leftX The X coordinate of the left side of the rectangle
     * @param topY The Y coordinate of the top of the rectangle
     * @param rightX The X coordinate of the right side of the rectangle
     * @param bottomY The Y coordinate of the bottom of the rectangle
     * @param rx The x-radius of the oval used to round the corners
     * @param ry The y-radius of the oval used to round the corners
     * @param topLeft
     * @param topRight
     * @param bottomRight
     * @param bottomLeft
     * @return
     */
    public static Path RoundedRect(float leftX, float topY, float rightX, float bottomY, float rx,
                                   float ry, boolean topLeft, boolean topRight, boolean
                                           bottomRight, boolean bottomLeft) {
        Path path = new Path();
        if (rx < 0) rx = 0;
        if (ry < 0) ry = 0;
        float width = rightX - leftX;
        float height = bottomY - topY;
        if (rx > width / 2) rx = width / 2;
        if (ry > height / 2) ry = height / 2;
        float widthMinusCorners = (width - (2 * rx));
        float heightMinusCorners = (height - (2 * ry));

        path.moveTo(rightX, topY + ry);
        if (topRight)
            path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
        else{
            path.rLineTo(0, -ry);
            path.rLineTo(-rx,0);
        }
        path.rLineTo(-widthMinusCorners, 0);
        if (topLeft)
            path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
        else{
            path.rLineTo(-rx, 0);
            path.rLineTo(0,ry);
        }
        path.rLineTo(0, heightMinusCorners);

        if (bottomLeft)
            path.rQuadTo(0, ry, rx, ry);//bottom-left corner
        else{
            path.rLineTo(0, ry);
            path.rLineTo(rx,0);
        }

        path.rLineTo(widthMinusCorners, 0);
        if (bottomRight)
            path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
        else{
            path.rLineTo(rx,0);
            path.rLineTo(0, -ry);
        }

        path.rLineTo(0, -heightMinusCorners);

        path.close();//Given close, last lineto can be removed.

        return path;
    }
}

Using the transformation with Picasso.

Picasso.with(this)
        .load("http://www.gettyimages.ca/gi-resources/images/Homepage/Hero/UK/CMS_Creative_164657191_Kingfisher.jpg")
        .transform(new RoundCornersTransformation(20, 20, true, true))
        .into(anImageView);

Making round corners by overriding the onDraw method of the ImageView. RoundCornersImageView.java

import android.annotation.TargetApi;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.os.Build;
import android.util.AttributeSet;
import android.widget.ImageView;

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

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

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

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

    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        super.onLayout(changed, left, top, right, bottom);
    }

    @Override
    protected boolean setFrame(int l, int t, int r, int b) {
        return super.setFrame(l, t, r, b);
    }

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

Use it like this:

<com.example.roundcorners.RoundCornersImageView
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:scaleType="fitXY"
    android:layout_marginBottom="10dp"
    android:src="@drawable/fire"/>

Making a custom ImageView with options to choose the corners to be rounded.
attrs.xml

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <declare-styleable name="RoundishImageView">
        <attr name="cornerRadius" format="dimension" />
        <attr name="roundedCorners">
            <flag name="topLeft" value="1" />
            <flag name="topRight" value="2" />
            <flag name="bottomRight" value="4" />
            <flag name="bottomLeft" value="8" />
            <flag name="all" value="15" />
        </attr>
    </declare-styleable>
</resources>

RoundishImageView.java

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Path;
import android.graphics.RectF;
import android.util.AttributeSet;
import android.util.Log;
import android.widget.ImageView;

public class RoundishImageView extends ImageView {

    public static final int CORNER_NONE = 0;
    public static final int CORNER_TOP_LEFT = 1;
    public static final int CORNER_TOP_RIGHT = 2;
    public static final int CORNER_BOTTOM_RIGHT = 4;
    public static final int CORNER_BOTTOM_LEFT = 8;
    public static final int CORNER_ALL = 15;

    private final RectF cornerRect = new RectF();
    private final Path path = new Path();
    private int cornerRadius;
    private int roundedCorners;

    public RoundishImageView(Context context) {
        this(context, null);
    }

    public RoundishImageView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

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

        TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.RoundishImageView);
        cornerRadius = a.getDimensionPixelSize(R.styleable.RoundishImageView_cornerRadius, 0);
        roundedCorners = a.getInt(R.styleable.RoundishImageView_roundedCorners, CORNER_NONE);
        a.recycle();
    }

    public void setCornerRadius(int radius) {
        cornerRadius = radius;
        setPath();
        invalidate();
    }

    public int getRadius() {
        return cornerRadius;
    }

    public void setRoundedCorners(int corners) {
        roundedCorners = corners;
        setPath();
        invalidate();
    }

    public int getRoundedCorners() {
        return roundedCorners;
    }

    @Override
    protected void onSizeChanged(int w, int h, int oldw, int oldh) {
        super.onSizeChanged(w, h, oldw, oldh);
        setPath();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        if (!path.isEmpty()) {
            canvas.clipPath(path);
        }
        super.onDraw(canvas);
    }

    private void setPath() {
        path.rewind();

        if (cornerRadius >= 1f && roundedCorners != CORNER_NONE) {
            final int width = getWidth();
            final int height = getHeight();
            final float twoRadius = cornerRadius * 2;
            cornerRect.set(-cornerRadius, -cornerRadius, cornerRadius, cornerRadius);

            if (isRounded(CORNER_TOP_LEFT)) {
                cornerRect.offsetTo(0f, 0f);
                path.arcTo(cornerRect, 180f, 90f);
            } else {
                path.moveTo(0f, 0f);
            }

            if (isRounded(CORNER_TOP_RIGHT)) {
                cornerRect.offsetTo(width - twoRadius, 0f);
                path.arcTo(cornerRect, 270f, 90f);
            } else {
                path.lineTo(width, 0f);
            }

            if (isRounded(CORNER_BOTTOM_RIGHT)) {
                cornerRect.offsetTo(width - twoRadius, height - twoRadius);
                path.arcTo(cornerRect, 0f, 90f);
            } else {
                path.lineTo(width, height);
            }

            if (isRounded(CORNER_BOTTOM_LEFT)) {
                cornerRect.offsetTo(0f, height - twoRadius);
                path.arcTo(cornerRect, 90f, 90f);
            } else {
                path.lineTo(0f, height);
            }

            path.close();
        }
    }

    private boolean isRounded(int corner) {
        return (roundedCorners & corner) == corner;
    }
}

Use it like this:

<com.example.roundcorners.RoundishImageView
    android:layout_width="match_parent"
    android:layout_height="200dp"
    android:layout_marginBottom="10dp"
    android:adjustViewBounds="true"
    android:scaleType="fitXY"
    android:src="@drawable/fire"
    app:cornerRadius="@dimen/round_corner_radius"
    app:roundedCorners="topLeft|bottomRight" />

Complete example in Github

Search within Codexpedia

Custom Search

Search the entire web

Custom Search