圆角ImageView/圆形ImageView

先上效果

在这里插入图片描述
实现圆角的方法很多,这里采用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" />
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值