使用TransitionDrawable实现Drawable淡入淡出,能否保持宽高比?
解决TransitionDrawable背景过渡时图片拉伸/挤压的问题
问题根源
- 代码末尾的
backgroundimage.setImageResource(imageResource)会直接覆盖你设置的TransitionDrawable,导致过渡效果被打断,最终显示未经过缩放处理的原图,这是图片拉伸的核心原因。 - TransitionDrawable中的新旧Drawable未统一缩放规则,即使ImageView设置了
CENTER_CROP,内部Drawable的显示逻辑可能不匹配。 - 原代码用同步
get()加载Bitmap会阻塞主线程,存在ANR风险。
修正方案
移除覆盖TransitionDrawable的代码,统一新旧Drawable的缩放逻辑,改用异步加载避免主线程阻塞,修正后的代码如下:
val imageResource = setSpecialImage(principalEvent) if (isFirstTimeLoadingBackground) { isFirstTimeLoadingBackground = false // 首次加载直接用Picasso处理,保证初始图片应用正确缩放 backgroundimage.scaleType = ImageView.ScaleType.CENTER_CROP Picasso.get().load(imageResource) .fit() .centerCrop() .into(backgroundimage) } else { // 获取ImageView实际尺寸,而非屏幕尺寸(适配非全屏场景) val targetWidth = backgroundimage.width val targetHeight = backgroundimage.height // 异步加载新图片,避免阻塞主线程 Picasso.get().load(imageResource) .resize(targetWidth, targetHeight) .centerCrop() .into(object : Target { override fun onBitmapLoaded(bitmap: Bitmap?, from: Picasso.LoadedFrom?) { bitmap?.let { val newDrawable = BitmapDrawable(resources, it).apply { // 设置gravity与ImageView的scaleType保持一致 gravity = Gravity.CENTER_CROP } val oldDrawable = backgroundimage.drawable val transition = TransitionDrawable(arrayOf(oldDrawable, newDrawable)) backgroundimage.setImageDrawable(transition) backgroundimage.scaleType = ImageView.ScaleType.CENTER_CROP transition.startTransition(100) } } override fun onBitmapFailed(e: Exception?, errorDrawable: Drawable?) { // 加载失败时降级处理 backgroundimage.setImageResource(imageResource) } override fun onPrepareLoad(placeHolderDrawable: Drawable?) {} }) }
关键优化点
- 移除了
backgroundimage.setImageResource(imageResource),保证过渡效果完整执行。 - 用ImageView自身尺寸替代屏幕尺寸,适配非全屏的ImageView场景。
- 异步加载Bitmap,避免主线程阻塞。
- 给新Drawable设置
Gravity.CENTER_CROP,确保新旧Drawable的缩放逻辑完全统一,过渡过程中不会出现拉伸挤压。
内容的提问来源于stack exchange,提问作者LiamTheKid
相关产品推荐
相关产品推荐

