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() 方法来实现,不过定制能力差一些。

相关推荐
海棠一号1 分钟前
Android Settings 数据库生成、监听与默认值配置
android·数据库
雨白28 分钟前
Fragment 入门教程:从核心概念到实践操作
android
烈焰晴天35 分钟前
使用ReactNative加载Svga动画支持三端【Android/IOS/Harmony】
android·react native·ios
阿幸软件杂货间1 小时前
PPT转图片拼贴工具 v2.0
android·python·powerpoint
sg_knight1 小时前
Flutter嵌入式开发实战 ——从树莓派到智能家居控制面板,打造工业级交互终端
android·前端·flutter·ios·智能家居·跨平台
Digitally2 小时前
如何轻松将视频从安卓设备传输到电脑?
android·电脑·音视频
Dola_Pan2 小时前
Android四大组件通讯指南:Kotlin版组件茶话会
android·开发语言·kotlin
hopetomorrow3 小时前
学习路之PHP--webman安装及使用
android·学习·php
aningxiaoxixi3 小时前
android 之 Tombstone
android
移动开发者1号3 小时前
应用启动性能优化与黑白屏处理方案
android·kotlin