先看下效果图:
实现代码:
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)
}
否则会出现圆角是黑色的情况