Android|Android 圆角&圆形ImageView

Android圆角、圆形ImageView的实现方式有很多,这应该是最简单的实现方式,通过裁剪画布canvas,但是clipPath()方法不支持抗锯齿,图片边缘会有明显的毛糙感

class XImageView : ImageView {private var currentStyle = 0 private val STYLE_ROUND = 1 private val STYLE_CIRCLE = 2 private var radius = 0f private val path = Path() private var rectF: RectF = RectF()constructor(context: Context) : this(context, null)constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initAttr(context, attrs) }private fun initAttr(context: Context, attrs: AttributeSet?) { val typedArray = context.obtainStyledAttributes(attrs, R.styleable.XImageView) radius = typedArray.getDimension(R.styleable.XImageView_radius, radius) currentStyle = typedArray.getInt(R.styleable.XImageView_showType, STYLE_ROUND) typedArray.recycle() }override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) if (currentStyle == STYLE_CIRCLE) { val min = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)) setMeasuredDimension(min, min) } rectF.set(0f, 0f, width.toFloat(), height.toFloat()) }override fun onDraw(canvas: Canvas) { path.reset() when (currentStyle) { STYLE_ROUND -> { if (radius > 0) { path.addRoundRect(rectF, radius, radius, Path.Direction.CW) } } STYLE_CIRCLE -> { val circle = width / 2f path.addCircle(circle, circle, circle, Path.Direction.CW) } } if (!path.isEmpty) { canvas.clipPath(path) } super.onDraw(canvas) } }

【Android|Android 圆角&圆形ImageView】另一种方法是使用图像的 Alpha 合成模式,过程就是先绘制目标图像,也就是图片;再绘制一个圆角矩形或者圆形,这样最终目标图像和原图像重合的区域。
class XImageView : ImageView {private var currentStyle = 0 private val STYLE_ROUND = 1 private val STYLE_CIRCLE = 2 private var radius = 0f private val path = Path() private var rectF: RectF = RectF() private val paint by lazy { Paint().apply { isAntiAlias = true style = Paint.Style.FILL xfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN) } }constructor(context: Context) : this(context, null)constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) { initAttr(context, attrs) }private fun initAttr(context: Context, attrs: AttributeSet?) { val typedArray = context.obtainStyledAttributes(attrs, R.styleable.XImageView) radius = typedArray.getDimension(R.styleable.XImageView_radius, radius) currentStyle = typedArray.getInt(R.styleable.XImageView_showType, STYLE_ROUND) typedArray.recycle() }override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { super.onMeasure(widthMeasureSpec, heightMeasureSpec) if (currentStyle == STYLE_CIRCLE) { val min = Math.min(MeasureSpec.getSize(widthMeasureSpec), MeasureSpec.getSize(heightMeasureSpec)) setMeasuredDimension(min, min) } rectF.set(0f, 0f, width.toFloat(), height.toFloat()) }override fun onDraw(canvas: Canvas) { path.reset() canvas.saveLayer(rectF, null, Canvas.ALL_SAVE_FLAG) super.onDraw(canvas) when (currentStyle) { STYLE_ROUND -> { if (radius > 0) { path.addRoundRect(rectF, radius, radius, Path.Direction.CW) } } STYLE_CIRCLE -> { val circle = width / 2f path.addCircle(circle, circle, circle, Path.Direction.CW) } } canvas.drawPath(path, paint) canvas.restore() } }

    推荐阅读