Glide自定义Transformation实现图片部分圆角

自定义Glide的Transformation实现部分圆角的文章和代码在网上有很多,原本我也是随便在网上找一份Glide 加载部分圆角图片在项目中直接使用,但在使用过程居然遇到Bug,所以去查看了官方文档,发现自定义的Transformation忘掉了最关键的部分,即重写equals()/hashCode()两个函数,虽然在一般场景下可以正常使用,但在RecyclerView这种会加载大量图片的场景下,自定义的transform且未重写equals()/hashCode()会导致Bug。

(emmm,具体是什么Bug我忘了,大概是滑动卡顿?因为是很久之前遇到的问题,现在补的文章)

先来看看官方文档:

官方文档

官方文章中注明equals()/hashCode()/updateDiskCacheKey()三个方法是必须被重写以使得磁盘和内存缓存正确地工作。不重写equals()/hashCode()磁盘缓存就可能无法正常工作,虽然可以通过编译,但使用时会引起内存泄露等问题。

最后附上修改后的RoundedCornersTransform,目前可以正常使用:

//Koltin版本
class RoundedCornersTransform(
    context: Context?,
    var radius: Float,
    var leftTop: Boolean = true,
    var rightTop: Boolean = true,
    var leftBottom: Boolean = true,
    var rightBottom: Boolean = true
) :
    Transformation {
    private val mBitmapPool: BitmapPool = Glide.get(context!!).bitmapPool

    private val id = javaClass.name
    private val idBytes = id.toByteArray(Charsets.UTF_8);

    override fun transform(
        context: Context,
        resource: Resource,
        outWidth: Int,
        outHeight: Int
    ): Resource {
        val source: Bitmap = resource.get()
        var finalWidth: Int
        var finalHeight: Int
        //输出目标的宽高或高宽比例
        var scale: Float
        if (outWidth > outHeight) {
            //如果 输出宽度 > 输出高度 求高宽比
            scale = outHeight.toFloat() / outWidth.toFloat()
            finalWidth = source.width
            //固定原图宽度,求最终高度
            finalHeight = (source.width.toFloat() * scale).toInt()
            if (finalHeight > source.height) {
                //如果 求出的最终高度 > 原图高度 求宽高比
                scale = outWidth.toFloat() / outHeight.toFloat()
                finalHeight = source.height
                //固定原图高度,求最终宽度
                finalWidth = (source.height.toFloat() * scale).toInt()
            }
        } else if (outWidth < outHeight) {
            //如果 输出宽度 < 输出高度 求宽高比
            scale = outWidth.toFloat() / outHeight.toFloat()
            finalHeight = source.height
            //固定原图高度,求最终宽度
            finalWidth = (source.height.toFloat() * scale).toInt()
            if (finalWidth > source.width) {
                //如果 求出的最终宽度 > 原图宽度 求高宽比
                scale = outHeight.toFloat() / outWidth.toFloat()
                finalWidth = source.width
                finalHeight = (source.width.toFloat() * scale).toInt()
            }
        } else {
            //如果 输出宽度=输出高度
            finalHeight = source.height
            finalWidth = finalHeight
        }

        //修正圆角
        radius *= finalHeight.toFloat() / outHeight.toFloat()
        val outBitmap: Bitmap = mBitmapPool[finalWidth, finalHeight, Bitmap.Config.ARGB_8888]
        val canvas = Canvas(outBitmap)
        val paint = Paint()
        //关联画笔绘制的原图bitmap
        val shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
        //计算中心位置,进行偏移
        val width: Int = (source.width - finalWidth) / 2
        val height: Int = (source.height - finalHeight) / 2
        if (width != 0 || height != 0) {
            val matrix = Matrix()
            matrix.setTranslate((-width).toFloat(), (-height).toFloat())
            shader.setLocalMatrix(matrix)
        }
        paint.shader = shader
        paint.isAntiAlias = true
        val rectF = RectF(0.0f, 0.0f, canvas.width.toFloat(), canvas.height.toFloat())
        //先绘制圆角矩形
        canvas.drawRoundRect(rectF, radius, radius, paint)

        //左上角圆角
        if (!leftTop) {
            canvas.drawRect(0f, 0f, radius, radius, paint)
        }
        //右上角圆角
        if (!rightTop) {
            canvas.drawRect(canvas.width - radius, 0f, canvas.width.toFloat(), radius, paint)
        }
        //左下角圆角
        if (!leftBottom) {
            canvas.drawRect(0f, canvas.height - radius, radius, canvas.height.toFloat(), paint)
        }
        //右下角圆角
        if (!rightBottom) {
            canvas.drawRect(
                canvas.width - radius,
                canvas.height - radius,
                canvas.width.toFloat(),
                canvas.height.toFloat(),
                paint
            )
        }
        return BitmapResource.obtain(outBitmap, mBitmapPool)!!
    }

    /** must override */
    override fun equals(other: Any?): Boolean {
        return other is RoundedCornersTransform
    }

    /** must override */
    override fun hashCode(): Int {
        return id.hashCode()
    }

    /** must override */
    override fun updateDiskCacheKey(messageDigest: MessageDigest) {
        messageDigest.update(idBytes)
    }
}

RoundedCornersTransform使用:

//默认裁剪四个圆角,不需要设置圆角,对应参数设为false
Glide.with(context)
            .load(item.coverUrl)
            .apply(
                RequestOptions().transform(
                    CenterCrop(), RoundedCornersTransform(
                        context, 8f,
                        leftBottom = false,
                        rightBottom = false
                    )
                )
            )
            .into(holder.getView(R.id.img_icon))

你可能感兴趣的:(Glide自定义Transformation实现图片部分圆角)