API 27及以下版本如何修改视图(含MaterialCardView)阴影颜色?
修改MaterialCardView阴影颜色(API <28)的可行方案
一、原生实现方式
由于API 28以下系统不支持View#setOutlineAmbientShadowColor()和View#setOutlineSpotShadowColor()方法,可通过自定义绘制模拟带颜色的阴影,步骤如下:
- 关闭MaterialCardView原生阴影
materialCardView.setCardElevation(0f); materialCardView.setUseCompatPadding(true); // 可选,避免布局偏移
- 自定义阴影Drawable
通过Paint.setShadowLayer()实现带颜色的模糊阴影,同时匹配CardView圆角:
public class ColoredShadowDrawable extends Drawable { private final Paint mShadowPaint; private RectF mShadowRect; private final float mCornerRadius; private final int mShadowColor; private final float mShadowRadius; private final float mShadowOffsetX; private final float mShadowOffsetY; public ColoredShadowDrawable(int shadowColor, float shadowRadius, float offsetX, float offsetY, float cornerRadius) { mShadowColor = shadowColor; mShadowRadius = shadowRadius; mShadowOffsetX = offsetX; mShadowOffsetY = offsetY; mCornerRadius = cornerRadius; mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG); mShadowPaint.setColor(Color.TRANSPARENT); mShadowPaint.setShadowLayer(mShadowRadius, mShadowOffsetX, mShadowOffsetY, mShadowColor); } @Override public void draw(@NonNull Canvas canvas) { canvas.drawRoundRect(mShadowRect, mCornerRadius, mCornerRadius, mShadowPaint); } @Override protected void onBoundsChange(Rect bounds) { super.onBoundsChange(bounds); // 留出阴影绘制空间 mShadowRect = new RectF( bounds.left + mShadowRadius, bounds.top + mShadowRadius, bounds.right - mShadowRadius, bounds.bottom - mShadowRadius ); } @Override public void setAlpha(int alpha) { mShadowPaint.setAlpha(alpha); } @Override public void setColorFilter(@Nullable ColorFilter colorFilter) { mShadowPaint.setColorFilter(colorFilter); } @Override public int getOpacity() { return PixelFormat.TRANSLUCENT; } }
- 将自定义Drawable设置给CardView
可通过setForeground()或ViewOverlay添加阴影:
ColoredShadowDrawable shadowDrawable = new ColoredShadowDrawable( Color.parseColor("#FF6200EE"), // 自定义阴影颜色 12f, // 阴影模糊半径 0f, // X轴偏移 4f, // Y轴偏移 materialCardView.getRadius() // 和CardView圆角保持一致 ); materialCardView.setForeground(shadowDrawable);
二、性能优异的第三方库
如果不想手动实现,以下第三方库经过性能优化,兼容低版本API:
CardViewEx
扩展原生CardView,直接支持通过XML属性设置阴影颜色、半径和偏移,内部采用硬件加速绘制,性能接近原生:<com.example.cardviewex.CardViewEx android:layout_width="match_parent" android:layout_height="wrap_content" app:cardCornerRadius="8dp" app:shadowColor="@color/custom_shadow" app:shadowRadius="12dp" app:shadowOffsetY="4dp"> <!-- 子布局 --> </com.example.cardviewex.CardViewEx>DynamicShadowLayout
轻量级阴影布局容器,支持任意子View(包括MaterialCardView),支持自定义阴影颜色、方向、模糊度,兼容API 16+,全程硬件加速,性能优异:<com.example.dynamicshadowlayout.DynamicShadowLayout android:layout_width="match_parent" android:layout_height="wrap_content" app:shadow_color="@color/blue_shadow" app:shadow_blur="10dp" app:shadow_offset="5dp"> <com.google.android.material.card.MaterialCardView android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_margin="10dp" app:cardCornerRadius="8dp"> <!-- 子布局 --> </com.google.android.material.card.MaterialCardView> </com.example.dynamicshadowlayout.DynamicShadowLayout>
内容的提问来源于stack exchange,提问作者Mateus Bauer
相关产品推荐
相关产品推荐

