美文网首页
Android 圆角&圆形ImageView

Android 圆角&圆形ImageView

作者: 猪爸爸Hulk | 来源:发表于2018-08-23 14:45 被阅读109次

    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

          本文链接:https://www.haomeiwen.com/subject/octmiftx.html