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

相关推荐
恋猫de小郭5 分钟前
Android Studio Cloud 正式上线,不只是 Android,随时随地改 bug
android·前端·flutter
匹马夕阳6 小时前
(十八)安卓开发中的后端接口调用详讲解
android
Pigwantofly7 小时前
鸿蒙ArkTS实战:从零打造智能表达式计算器(附状态管理+路由传参核心实现)
android·华为·harmonyos
Gracker8 小时前
Android Weekly #202514
android
binderIPC9 小时前
Android之JNI详解
android
林志辉linzh9 小时前
安卓AssetManager【一】- 资源的查找过程
android·resources·assetmanger·安卓资源管理·aapt·androidfw·assetmanger2
_一条咸鱼_10 小时前
大厂Android面试秘籍:Activity 权限管理模块(七)
android·面试·android jetpack
lynn8570_blog10 小时前
通过uri获取文件路径手机适配
android·kotlin·android studio
JKIT沐枫11 小时前
PHP如何能获取网站上返回的数组指南
android·大数据
懋学的前端攻城狮12 小时前
Android一些基础-06-一个列表的基本写法
android