ShapeableImageView无法显示Shimmer占位符,仅空白直至图片加载完成
问题解决:ShapeableImageView搭配Glide Shimmer占位符不显示
ShapeableImageView的圆角是通过自身ShapeAppearanceOverlay实现的,Glide传入的ShimmerDrawable占位符不会自动继承该圆角裁剪逻辑,同时受ShapeableImageView的绘制优先级影响,导致占位符无法正常显示。以下是两种可行的解决方案:
方案一:用MaterialShapeDrawable包裹ShimmerDrawable(匹配圆角)
通过MaterialShapeDrawable给ShimmerDrawable添加和ShapeableImageView一致的圆角,确保占位符样式统一:
// 1. 构建Shimmer实例(保留原有逻辑) val shimmer = Shimmer.AlphaHighlightBuilder() .setDuration(1800) .setBaseAlpha(0.7f) .setHighlightAlpha(0.6f) .setDirection(Shimmer.Direction.LEFT_TO_RIGHT) .setAutoStart(true) .build() val shimmerDrawable = ShimmerDrawable().apply { setShimmer(shimmer) } // 2. 创建与ShapeableImageView一致的形状模型 // 替换成你style中定义的圆角尺寸,比如8dp对应的dimen值 val cornerSize = resources.getDimension(R.dimen.image_corner_radius) val shapeAppearanceModel = ShapeAppearanceModel() .toBuilder() .setAllCorners(CornerFamily.ROUNDED, cornerSize) .build() // 3. 用MaterialShapeDrawable包裹ShimmerDrawable,实现圆角裁剪 val shapedShimmerDrawable = MaterialShapeDrawable(shapeAppearanceModel).apply { paint.style = Paint.Style.FILL setDrawable(shimmerDrawable) } // 4. 加载图片时使用带圆角的Shimmer占位符 Glide.with(context) .load(imageUrl) .placeholder(shapedShimmerDrawable) .into(style_img)
方案二:使用ShimmerFrameLayout作为父容器(更直观)
将ShapeableImageView嵌套在ShimmerFrameLayout中,通过Glide的加载监听控制Shimmer的启停:
布局代码修改
<com.facebook.shimmer.ShimmerFrameLayout android:id="@+id/shimmer_container" android:layout_width="match_parent" android:layout_height="match_parent" app:shimmer_auto_start="true" app:shimmer_duration="1800" app:shimmer_base_alpha="0.7" app:shimmer_highlight_alpha="0.6" app:shimmer_direction="left_to_right"> <com.google.android.material.imageview.ShapeableImageView android:id="@+id/style_img" android:layout_width="match_parent" android:layout_height="match_parent" android:adjustViewBounds="true" android:contentDescription="@string/rapturous" android:scaleType="centerCrop" android:background="@color/shimmer_light_gray" <!-- 给占位加背景色,提升可见性 --> app:shapeAppearanceOverlay="@style/roundedCornersImageView" /> </com.facebook.shimmer.ShimmerFrameLayout>
加载代码修改
Glide.with(context) .load(imageUrl) .listener(object : RequestListener<Drawable> { override fun onLoadFailed(e: GlideException?, model: Any?, target: Target<Drawable>?, isFirstResource: Boolean): Boolean { shimmer_container.stopShimmer() shimmer_container.visibility = View.GONE return false } override fun onResourceReady(resource: Drawable?, model: Any?, target: Target<Drawable>?, dataSource: DataSource?, isFirstResource: Boolean): Boolean { shimmer_container.stopShimmer() shimmer_container.visibility = View.GONE return false } }) .into(style_img)
额外注意事项
- 确保Material Components库与Shimmer库版本兼容,建议使用最新稳定版
- 若方案一中的圆角尺寸获取麻烦,可直接硬编码(如
8f.dpToPx(),需自行实现dp转px扩展方法) - 给ShapeableImageView设置浅灰色背景,避免Shimmer因背景透明导致视觉上无效果
内容的提问来源于stack exchange,提问作者Mahin Munir
相关产品推荐
相关产品推荐

