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

另一种方法是使用图像的 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()
    }
}

你可能感兴趣的:(Android 圆角&圆形ImageView)