Android自定义View绘制内+外圆角

198 阅读1分钟

字面意思,view最外层的圆角,跟view里面某个区域的圆角 在有些场景下,会经常使用自定义view去绘制图标,还有各种下载状态,角标之类的 此时,有个需求需要你在基础上绘制一个带圆角的边框,基于这种前提下,外层的圆角显然不满足需求了

image.png 先来说下外圆角,方式很多种,也是常用的方式,xml,shape,imageview,cardview,图片框架等 自定义view可以使用 Outline 方式

clipToOutline = true
outlineProvider = object : ViewOutlineProvider() {
    override fun getOutline(view: View?, outline: Outline?) {
        radiusRectF.set(
            borderMargin.toInt(),
            borderMargin.toInt(),
            width - borderMargin.toInt(),
            height - borderMargin.toInt()
        )
        outline?.setRoundRect(radiusRectF, corner)
    }
}

但是你会发现这种方式只能达到外层圆角,如果外面有个边框,边框里面的图片就没圆角处理了 这种时候要么两种常用的方案 一种是使用纯xml布局,内嵌view,单独给某个view去处理圆角,这种相对简单,但是对于有些场景略显麻烦 第二种是使用自定义view绘制,在绘制过程中单独处理圆角

private val mode = PorterDuffXfermode(PorterDuff.Mode.DST_OUT)
private val mPaint = Paint().apply {
    isAntiAlias = true
    xfermode = mode
}
private val mPath = Path()

override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
    super.onSizeChanged(w, h, oldw, oldh)
    mPath.reset()
    //画布剪裁成圆角
    val p = Path()
    p.addRoundRect(
        iconRectF,
        floatArrayOf(corner, corner, corner, corner, corner, corner, corner, corner),
        Path.Direction.CCW
    )
    mPath.addRect(iconRectF, Path.Direction.CCW)
    mPath.op(p, Path.Op.DIFFERENCE)
}

override fun onDraw(canvas: Canvas) {
    icon?.let {
        it.bounds = iconRectF.toRect()
        it.draw(canvas)
    }
    canvas.drawPath(mPath, mPaint)
}

这样就轻松做到了内外圆角单独处理,而且每个角的圆角都能自定义,比较容易扩展