自定義Glide的Transformation實(shí)現(xiàn)部分圓角的文章和代碼在網(wǎng)上有很多阅羹,原本我也是隨便在網(wǎng)上找一份Glide 加載部分圓角圖片在項(xiàng)目中直接使用,但在使用過(guò)程居然遇到Bug,所以去查看了官方文檔卓箫,發(fā)現(xiàn)自定義的Transformation忘掉了最關(guān)鍵的部分,即重寫(xiě)equals()/hashCode()兩個(gè)函數(shù)淑倾,雖然在一般場(chǎng)景下可以正常使用鸥鹉,但在RecyclerView這種會(huì)加載大量圖片的場(chǎng)景下撑帖,自定義的transform且未重寫(xiě)equals()/hashCode()會(huì)導(dǎo)致Bug筐眷。
(emmm,具體是什么Bug我忘了垒手,大概是滑動(dòng)卡頓蒜焊?因?yàn)槭呛芫弥坝龅降膯?wèn)題,現(xiàn)在補(bǔ)的文章)
先來(lái)看看官方文檔:
官方文檔
官方文章中注明equals()/hashCode()/updateDiskCacheKey()三個(gè)方法是必須被重寫(xiě)以使得磁盤(pán)和內(nèi)存緩存正確地工作科贬。不重寫(xiě)equals()/hashCode()磁盤(pán)緩存就可能無(wú)法正常工作泳梆,雖然可以通過(guò)編譯,但使用時(shí)會(huì)引起內(nèi)存泄露等問(wèn)題榜掌。
最后附上修改后的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<Bitmap?> {
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<Bitmap?>,
outWidth: Int,
outHeight: Int
): Resource<Bitmap?> {
val source: Bitmap = resource.get()
var finalWidth: Int
var finalHeight: Int
//輸出目標(biāo)的寬高或高寬比例
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()
//關(guān)聯(lián)畫(huà)筆繪制的原圖bitmap
val shader = BitmapShader(source, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP)
//計(jì)算中心位置,進(jìn)行偏移
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使用:
//默認(rèn)裁剪四個(gè)圓角,不需要設(shè)置圓角憎账,對(duì)應(yīng)參數(shù)設(shè)為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))