先上效果
实现圆角的方法很多,这里采用Paint.xfermode=PorterDuffXfermode(PorterDuff.Mode.DST_IN) 实现圆角
1、 values/attrs.xml 自定义属性
<declare-styleable name="RichImageView">
<attr name="radius" format="dimension"/>
<attr name="type">
<enum name="circle" value="0"/>
<enum name="round" value="1"/>
</attr>
</declare-styleable>
2、RichImageView.kt
package com.guc.androiddemo.widget
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.util.Log
import androidx.appcompat.widget.AppCompatImageView
import com.guc.androiddemo.R
import java.lang.ref.WeakReference
/**
* Created by guc on 2022-6-28.
* Description:圆角ImageView
*/
class RichImageView(context: Context, attributeSet: AttributeSet?, defStyleAttr: Int = 0) :
AppCompatImageView(context, attributeSet, defStyleAttr) {
constructor(context: Context, attributeSet: AttributeSet?) : this(context, attributeSet, 0)
constructor(context: Context) : this(context, null)
companion object {
private const val TYPE_CIRCLE = 0
private const val TYPE_ROUND = 1
private const val DEFAULT_RADIUS = 10 //圆角默认值
private const val TAG = "RichImageView"
}
private var type = TYPE_CIRCLE
private var radius = DEFAULT_RADIUS
private val mXfermode = PorterDuffXfermode(PorterDuff.Mode.DST_IN) //相交处绘制目标图(先绘制的)
private val mPaint = Paint()
private var mWeakBitmap: WeakReference<Bitmap>? = null
private var mMaskBitmap: Bitmap? = null
init {
mPaint.apply {
isAntiAlias = true
}
context.obtainStyledAttributes(attributeSet, R.styleable.RichImageView).apply {
radius = getDimensionPixelSize(R.styleable.RichImageView_radius, DEFAULT_RADIUS)
type = getInt(R.styleable.RichImageView_type, TYPE_CIRCLE)
recycle()
}
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec)
if (type == TYPE_CIRCLE) {
val w = measuredWidth.coerceAtMost(measuredHeight)
setMeasuredDimension(w, w)
}
}
@SuppressLint("DrawAllocation")
override fun onDraw(canvas: Canvas) {
var bitmap = mWeakBitmap?.get()
if (bitmap == null || bitmap.isRecycled) {
val dra = drawable
if (dra != null) {
//获取图片宽高
val w = dra.intrinsicWidth
val h = dra.intrinsicHeight
bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val cans = Canvas(bitmap)
val scale =
if (type == TYPE_ROUND) (width * 1f / w).coerceAtLeast(height * 1f / h) else width * 1f / w.coerceAtMost(
h
)
//根据缩放比例,设置bounds,相当于缩放图片了
dra.setBounds(0, 0, (w * scale).toInt(), (scale * h).toInt())
dra.draw(cans)
if (mMaskBitmap == null || mMaskBitmap!!.isRecycled) {
mMaskBitmap = getBitmap()
}
mPaint.apply {
reset()
isFilterBitmap = false
xfermode = mXfermode
}
//绘制图片
cans.drawBitmap(mMaskBitmap!!, 0f, 0f, mPaint)
mWeakBitmap = WeakReference(bitmap)
canvas.drawBitmap(bitmap, 0f, 0f, null)
mPaint.xfermode = null
}
} else {
mPaint.xfermode = null
canvas.drawBitmap(bitmap, 0.0f, 0.0f, mPaint)
}
// setLayerType(LAYER_TYPE_SOFTWARE, null) //关闭硬件加速
}
private fun getBitmap(): Bitmap {
return Bitmap.createBitmap(
width, height,
Bitmap.Config.ARGB_8888
).apply {
val canvas = Canvas(this)
val paint = Paint().apply {
isAntiAlias = true
color = Color.BLACK
}
if (type == TYPE_ROUND) {
canvas.drawRoundRect(
RectF(0f, 0f, width.toFloat(), height.toFloat()),
radius.toFloat(),
radius.toFloat(),
paint
)
} else {
canvas.drawCircle(width / 2f, height / 2f, height / 2f, paint)
}
}
}
}
3、使用示例
<-- 圆形 -->
<com.guc.androiddemo.widget.RichImageView
android:layout_width="100dp"
android:layout_height="120dp"
android:layout_marginLeft="10dp"
android:src="@drawable/bg_mv1"
app:radius="20dp"
app:type="circle" />
<-- 圆角 -->
<com.guc.androiddemo.widget.RichImageView
android:layout_width="100dp"
android:layout_height="120dp"
android:layout_marginLeft="10dp"
android:src="@drawable/bg_mv2"
app:radius="20dp"
app:type="round" />
<-- 直角即圆角下圆角半径为0 -->
<com.guc.androiddemo.widget.RichImageView
android:layout_width="100dp"
android:layout_height="120dp"
android:layout_marginLeft="10dp"
android:src="@drawable/bg_mv4"
app:radius="0dp"
app:type="round" />