Android 圆角的另一种实现方式(抗锯齿)

先看下效果图:

实现代码:

package com.example.myapplication.roundImage

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.MotionEvent
import android.view.View

/**
 * @Author: qqyang
 * @Date: 2021/12/2
 * @Description:
 */

class CustomRoundImage1 @JvmOverloads constructor(
    context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0
) : androidx.appcompat.widget.AppCompatImageView(context, attrs, defStyleAttr) {

    private val radii = floatArrayOf(99f, 99f, 99f, 99f, 99f, 99f, 99f, 99f)

    private var mWidth = 0
    private var mHeight = 0
    private val mPath by lazy { Path() }
    private val mPath1 by lazy { Path() }
    private val mPaint by lazy {
        Paint().apply {
            color = Color.TRANSPARENT
            isAntiAlias = true
            style = Paint.Style.FILL
        }
    }

    private val mXfermode by lazy { PorterDuffXfermode(PorterDuff.Mode.SRC) }

    private val mRegion by lazy {
        Region().apply {
            setPath(mPath1, Region(0, 0, width, height))
        }
    }

    init {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null)
    }

    override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
        super.onSizeChanged(w, h, oldw, oldh)
        mWidth = w
        mHeight = h
        mPath.addRect(0f, 0f, mWidth.toFloat(), mHeight.toFloat(), Path.Direction.CW)
        mPath1.addRoundRect(0f, 0f, mWidth.toFloat(), mHeight.toFloat(), radii, Path.Direction.CW)
        mPath.op(mPath1, Path.Op.XOR)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)
        mPaint.xfermode = mXfermode
        canvas.drawPath(mPath, mPaint)
    }

    override fun dispatchTouchEvent(event: MotionEvent): Boolean {
        if (!mRegion.contains(event.x.toInt(), event.y.toInt())) {
            return false
        }
        return super.dispatchTouchEvent(event)
    }

}

 实现原理:

1.先绘制原图

2.用透明色绘制4个圆角

着重说下四个圆角的绘制:

主要使用了 Path 的 op() 方法,

# Path.java
    public boolean op(@NonNull Path path, @NonNull Op op) {
        return op(this, path, op);
    }

需要两个 Path 对象,一个 Path 用来设置跟 ImageView 一样的大小,另一个 Path 用来设置需要设置的四个圆角,通过 Path.Op.XOR 参数(Path 的组合模式不明白的可以参考这篇文章),获取到一个 "包含两个 Path ,但不包含两者相交的部分 的 Path",绘制出来的样式如下图:

对比下原图:

我们需要做的就是绘制完原图,将 Paint 的颜色设置成透明,然后绘制组合过的 Path ,就可以绘制出圆角了. 

一定要设置

    init {
        setLayerType(View.LAYER_TYPE_SOFTWARE, null)
    }

否则会出现圆角是黑色的情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值