如何在XML中裁剪CardView内图片左下角实现半圆角效果?
CardView内图片左下角半圆角裁剪实现方案
以下方案均适配Android平台原生CardView组件:
方案1:使用Material Components ShapeableImageView(推荐,代码量最低)
无需自定义View,依赖官方Material库实现:
- 先在模块级
build.gradle中引入依赖(已引入可跳过):
implementation 'com.google.android.material:material:1.9.0'
- 布局中将普通ImageView替换为ShapeableImageView,嵌入CardView内部:
<androidx.cardview.widget.CardView android:layout_width="match_parent" android:layout_height="wrap_content" app:cardPreventCornerOverlap="true" app:cardElevation="4dp"> <com.google.android.material.imageview.ShapeableImageView android:id="@+id/coverIv" android:layout_width="match_parent" android:layout_height="200dp" android:scaleType="centerCrop" android:src="@drawable/your_image"/> </androidx.cardview.widget.CardView>
- 代码中仅给左下角设置圆角即可:
// 8为圆角大小,单位dp,可按需调整 val cornerRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8f, resources.displayMetrics) coverIv.shapeAppearanceModel = ShapeAppearanceModel.builder() .setBottomLeftCorner(CornerFamily.ROUNDED, cornerRadius) .build()
方案2:自定义ImageView实现(无第三方依赖)
如果不想引入Material库,可自定义ImageView重写绘制逻辑实现裁剪:
public class LeftBottomRoundImageView extends AppCompatImageView { // 圆角大小,单位px,可通过自定义属性从xml配置 private final float roundRadius = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 8, getResources().getDisplayMetrics()); private final Path clipPath = new Path(); public LeftBottomRoundImageView(Context context) { super(context); setLayerType(LAYER_TYPE_SOFTWARE, null); // 关闭硬件加速避免裁剪失效 } public LeftBottomRoundImageView(Context context, AttributeSet attrs) { super(context, attrs); setLayerType(LAYER_TYPE_SOFTWARE, null); } @Override protected void onDraw(Canvas canvas) { int width = getWidth(); int height = getHeight(); clipPath.reset(); // 构建仅左下角带圆角的裁剪区域 clipPath.moveTo(0, 0); clipPath.lineTo(width, 0); clipPath.lineTo(width, height); clipPath.lineTo(roundRadius, height); clipPath.quadTo(0, height, 0, height - roundRadius); clipPath.close(); canvas.clipPath(clipPath); super.onDraw(canvas); } }
直接将上述自定义View放入CardView中使用即可。
方案3:图片加载库Transformation实现
如果使用Glide、Picasso等图片加载库,可通过自定义Transformation实现裁剪,不侵入布局:
以Glide为例,自定义Transformation代码:
class LeftBottomRoundTransform(private val radiusDp: Int) : BitmapTransformation() { private val radiusPx = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, radiusDp.toFloat(), Resources.getSystem().displayMetrics ) override fun transform( pool: BitmapPool, toTransform: Bitmap, outWidth: Int, outHeight: Int ): Bitmap { val output = pool.get(outWidth, outHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(output) val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply { shader = BitmapShader(toTransform, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP) } val path = Path().apply { moveTo(0f, 0f) lineTo(outWidth.toFloat(), 0f) lineTo(outWidth.toFloat(), outHeight.toFloat()) lineTo(radiusPx, outHeight.toFloat()) quadTo(0f, outHeight.toFloat(), 0f, outHeight - radiusPx) close() } canvas.drawPath(path, paint) return output } override fun updateDiskCacheKey(messageDigest: MessageDigest) { messageDigest.update("left_bottom_round_$radiusDp".toByteArray()) } }
使用时直接添加到Glide加载逻辑即可:
Glide.with(context) .load(yourImageUrl) .transform(LeftBottomRoundTransform(8)) // 8为圆角大小,单位dp .into(coverIv)
内容的提问来源于stack exchange,提问作者Abhas Sharma
相关产品推荐
相关产品推荐

