MaterialShapeDrawable vs CardView:两种方式实现阴影效果对比

方式一:MaterialShapeDrawable

kotlin 复制代码
implementation "com.google.android.material:material:1.9.0"

MaterialShapeDrawable 是 Android Material Design 组件中的一个非常重要的 drawable 类,用于创建具有 Material Design 形状的背景或装饰效果。它支持各种形状、圆角、阴影、填充、描边和渐变等特性,可以用来为 View 添加更精细的外观效果。 引入

kotlin 复制代码
fun View.setShadow(
    context: Context,
    elevationWidth: Float = 10.dp2px().toFloat(),
    elevationColor: Int = Color.GRAY,
    hasStroke: Boolean = false,
    strokeColor: Int = Color.GRAY,
    strokeWidth: Float = 2.dp2px().toFloat()
) {
    val shapeAppearanceModel = ShapeAppearanceModel.builder()
        .setAllCorners(CornerFamily.ROUNDED, 10.dp2px().toFloat())
        .build()
    val materialShapeDrawable = MaterialShapeDrawable(shapeAppearanceModel).apply {
        fillColor = ColorStateList.valueOf(Color.WHITE) //可以设置各个状态颜色(默认颜色、点击颜色等)
        if (hasStroke) {
            //有轮廓
            val padding = (strokeWidth / 2).toInt()
            setStroke(strokeWidth, ColorStateList.valueOf(strokeColor)) //设置描边宽度及颜色
            setPadding(padding, padding, padding, padding) //设置padding
        }
        shadowCompatibilityMode = MaterialShapeDrawable.SHADOW_COMPAT_MODE_ALWAYS //阴影兼容模式
        initializeElevationOverlay(context)
        elevation = elevationWidth// 设置阴影高度
        setShadowColor(elevationColor) // 阴影颜色(半透明黑)
    }
    (this.parent as? ViewGroup)?.clipChildren = false
    this.background = materialShapeDrawable
}

利用MaterialShapeDrawable 写了一个View的扩展方法,下面来使用它

kotlin 复制代码
//XML文件
<TextView
    android:id="@+id/tv_shape"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:gravity="center"
    android:text="shadow" />

<!--ImageView外部套一层ViewGroup,以便能使用MaterialShapeDrawable-->
<FrameLayout
    android:id="@+id/fl_shape"
    android:layout_width="100dp"
    android:layout_height="100dp"
    android:layout_marginStart="50dp">

    <com.google.android.material.imageview.ShapeableImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@color/white"
        android:scaleType="centerCrop"
        android:src="@drawable/icon_cat_w"
        app:shapeAppearance="@style/roundedCornerStyle" />
</FrameLayout>

Activity中:

kotlin 复制代码
// 利用MaterialShapeDrawable来设置阴影
private val mTvShape: TextView by id(R.id.tv_shape)
private val mFlShape: FrameLayout by id(R.id.fl_shape)

mTvShape.setShadow(this, hasStroke = true, strokeWidth = 1.dp2px().toFloat())
mFlShape.setShadow(this, elevationColor = Color.RED)

执行结果:

可以看到阴影的颜色和大小都可以设置,还是挺方便的。以下是 MaterialShapeDrawable 中一些关键方法:

1、setFillColor(ColorStateList fillColor):设置 MaterialShapeDrawable 的填充颜色。可以设置为一个 ColorStateList,根据不同的状态(例如按下、聚焦等)设置不同的颜色。

2、setStrokeColor(ColorStateList strokeColor):设置 MaterialShapeDrawable 的描边颜色。与填充颜色类似,可以为描边设置 ColorStateList。

3、setStroke(float strokeWidth, @ColorInt int strokeColor):这个方法同时设置 MaterialShapeDrawable 的描边宽度和颜色。
4、setCornerSize(float cornerSize):设置所有角的圆角大小。你可以通过设置一个统一的 cornerSize 来修改所有角的大小。

5、setShapeAppearanceModel(ShapeAppearanceModel shapeAppearanceModel):该方法用于设置 MaterialShapeDrawable 的 ShapeAppearanceModel,可以通过该模型来设置形状、圆角、边框等。

6、 initializeElevationOverlay(Context context):初始化 elevation overlay 功能。如果 elevationOverlay 被启用,该方法将根据视图的 elevation 修改背景颜色(例如,给视图加上一个阴影)。
7、setShadowCompatibilityMode(@CompatibilityShadowMode int mode):设置阴影兼容模式。这个方法控制阴影何时以假阴影绘制,而不是使用原生的 elevation 阴影。

8、isElevationOverlayEnabled():检查 elevation overlay 是否启用。该方法返回 true 如果 elevation overlay 在当前主题中启用。

9、getOpacity():返回 MaterialShapeDrawable 的不透明度,通常会返回 TRANSLUCENT,表示这个 Drawable 可能是半透明的。

MaterialShapeDrawable 提供了许多灵活的配置选项,可以方便地根据需求设置视图的形状、圆角、阴影、颜色等。它是 Material Design 的核心组件之一,可以通过 ShapeAppearanceModel 来定义外观,而 elevation、shadow 等属性可以带来更丰富的视觉效果。

方式二:CardView

CardView 是 一个专门设计用于显示卡片样式布局的控件。它继承自 FrameLayout,具有丰富的功能,如圆角和阴影效果,非常适合构建具有卡片样式的界面。

kotlin 复制代码
<!--CardView-->
<androidx.cardview.widget.CardView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    android:layout_marginTop="20dp"
    app:cardCornerRadius="10dp"
    app:cardElevation="15dp">

    <ImageView
        android:id="@+id/iv_shadow"
        android:layout_width="100dp"
        android:layout_height="100dp"
        android:scaleType="centerCrop"
        android:src="@drawable/icon_cat_w" />
</androidx.cardview.widget.CardView>

效果图:

CardView 与阴影相关的几个属性:

cardElevation: 控制卡片的高度(Z 轴方向),值越大,阴影越明显。 cardMaxElevation: 设置卡片的最大阴影范围,用于限制阴影扩散的程度。 cardUseCompatPadding:在低版本兼容模式下,是否为 CardView 添加额外的内边距以显示阴影。

除了上面两种,还可以考虑直接使用View.setElevation() 方法来实现,不过定制能力差一些。

相关推荐
Rytter6 小时前
Android逆向学习(八)Xposed快速上手(上)
android·学习
林十一npc6 小时前
Fiddler抓取APP端,HTTPS报错全解析及解决方案(一篇解决常见问题)
android·前端·网络协议·https·fiddler·接口测试
东风西巷7 小时前
AM剪辑软件汉化版:简单易用,开启视频创作之旅
android·智能手机·音视频·软件需求
这个家伙很笨7 小时前
了解Android studio 初学者零基础推荐(1)
android·笔记·android studio
Lovely Ruby7 小时前
Hbuilder 开发鸿蒙应用,打包成 hap 格式(并没有上架应用商店,只安装调试用)
android·华为·harmonyos
帅得不敢出门9 小时前
Android Framework学习三:zygote剖析
android·java·学习·framework·安卓·zygote
爱英语的程序员10 小时前
分享一个Android中文汉字手写输入法并带有形近字联想功能
android·手写输入法·android手写输入法·手写识别
Ya-Jun10 小时前
性能优化实践:性能监控体系
android·开发语言·flutter·ios·性能优化
Ya-Jun10 小时前
性能优化实践:内存优化技巧
android·flutter·ios·性能优化
Leoysq10 小时前
为 Unity 项目添加自定义 USB HID 设备支持 (适用于 PC 和 Android/VR)-任何手柄、无人机手柄、摇杆、方向盘
android·unity·vr