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 14:ShellTransition 屏幕旋转过程深度剖析
android·智能手机·性能优化·framework·性能·屏幕旋转·rotation
美狐美颜SDK开放平台1 天前
开发直播APP时如何接入视频美颜SDK?开发流程与注意事项
android·人工智能·计算机视觉·音视频·直播美颜sdk
AFinalStone1 天前
Android7 SystemUI源码解析(七)Keyguard锁屏模块深度解析
android·systemui
致远ccc1 天前
Google Play 上架前如何测试 App?多国家 Android 环境测试
android·app测试·googleplay·多国家应用测试
ttyyttemo1 天前
Kotlin 协程中的 Job 结构化并发与取消
android
sun0077001 天前
tbox 4g/5g切换,导致wan ip 改变,导致车机旧网络不可用。需要重启车机才行
android
其实防守也摸鱼1 天前
内网穿透与反向代理:原理、工具与实战指南
android·大数据·运维·安全·网络安全·自动化·渗透
AFinalStone1 天前
Android7 SystemUI 源码解析(四)NavigationBar 导航栏与 SystemBars
android·systemui
JMchen1 天前
属性动画原理与高级动画实现
android·kotlin·canvas
AFinalStone1 天前
Android7 SystemUI 源码解析(二)启动流程深度解析
android·systemui