参考项目:GcsSloop/rclayout
实现1,利用Canvas.clipPath来实现(无法去除锯齿效果)
package com.bu_ish.blog; import android.content.Context; import android.graphics.Canvas; import android.graphics.Path; import android.util.AttributeSet; import androidx.appcompat.widget.AppCompatImageView; public class RoundedImageView extends AppCompatImageView { private int cornerRadius = 12; private Path path; public RoundedImageView(Context context, AttributeSet attrs) { super(context, attrs); path = new Path(); } @Override protected void onDraw(Canvas canvas) { ViewUtils.clipRoundedPathForCanvas(this, canvas, path, cornerRadius); super.onDraw(canvas); } public void setCornerRadius(int radius) { cornerRadius = radius; invalidate(); } }
package com.bu_ish.blog; import android.graphics.Canvas; import android.graphics.Path; import android.view.View; public class ViewUtils { public static void clipRoundedPathForCanvas(View view, Canvas canvas, Path path, int cornerRadius) { makePathRounded(view, path, cornerRadius); canvas.clipPath(path); } private static void makePathRounded(View view, Path path, int cornerRadius) { int width = view.getWidth(), height = view.getHeight(); path.moveTo(cornerRadius, 0); path.lineTo(width - cornerRadius, 0); path.quadTo(width, 0, width, cornerRadius); path.lineTo(width, height - cornerRadius); path.quadTo(width, height, width - cornerRadius, height); path.lineTo(cornerRadius, height); path.quadTo(0, height, 0, height - cornerRadius); path.lineTo(0, cornerRadius); path.quadTo(0, 0, cornerRadius, 0); } }
实现2,利用Canvas.drawPath实现,可抗锯齿
package com.bu_ish.blog; import android.content.Context; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Path; import android.graphics.PorterDuff; import android.graphics.PorterDuffXfermode; import android.graphics.RectF; import android.util.AttributeSet; import androidx.appcompat.widget.AppCompatImageView; public class RoundedImageView extends AppCompatImageView { private final Path roundedPath, pathToDraw; private final RectF rect; private final Paint paint; private int cornerRadius = 50; public RoundedImageView(Context context, AttributeSet attrs) { super(context, attrs); roundedPath = new Path(); pathToDraw = new Path(); rect = new RectF(); paint = new Paint(); initializePaint(); } @Override protected void onDraw(Canvas canvas) { canvas.saveLayer(null, null, Canvas.ALL_SAVE_FLAG); super.onDraw(canvas); addRoundRectToRoundedPath(); preparePathToDraw(); canvas.drawPath(pathToDraw, paint); canvas.restore(); } private void initializePaint() { paint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.DST_OUT)); paint.setStyle(Paint.Style.FILL); paint.setAntiAlias(true); } private void addRoundRectToRoundedPath() { rect.left = 0; rect.top = 0; rect.right = getWidth(); rect.bottom = getHeight(); roundedPath.addRoundRect(rect, cornerRadius, cornerRadius, Path.Direction.CW); } private void preparePathToDraw() { pathToDraw.reset(); pathToDraw.addRect(0, 0, getWidth(), getHeight(), Path.Direction.CW); pathToDraw.op(roundedPath, Path.Op.DIFFERENCE); } public void setCornerRadius(int radius) { cornerRadius = radius; invalidate(); } }
一个比较好的开源项目
vinc3m1/RoundedImageView: A fast ImageView that supports rounded corners, ovals, and circles.