Android MaterialShapeDrawable 强大的Drawable类(形状,边框,阴影,动态变化)

MaterialShapeDrawable 是 Google Material Design 库中一个强大的 Drawable 类,主要用于实现带形状和阴影效果的的背景绘制,圆角,边框,阴影等复杂形状以动态效果的设置.

注意:

  • 不支持渐变色

1. 主要类和概念

  • MaterialShapeDrawable
    继承自 Drawable,核心绘制类,负责绘制形状、填充颜色、描边和阴影。
  • ShapeAppearanceModel
    形状模型,定义边角的形状(圆角、切角)和大小。可通过 Builder 模式灵活创建。
  • CornerTreatment
    角的处理方式,比如圆角 (RoundedCornerTreatment)、切角 (CutCornerTreatment)。
  • EdgeTreatment
    边的处理,比如带凹槽的边。
  • FillColorStrokeColor
    Drawable 的填充色和边框色,支持 ColorStateList,可以响应状态变化。
  • Shadow
    MaterialShapeDrawable 支持绘制阴影,适配 Material Design 阴影规范。

2.功能实现

MaterialShapeDrawable 主要用来实现各种各样的形状纯色图形

  • 圆角
  • 圆形
  • 其他形状
  • 边框
  • 阴影
  • 动态角度改变

2.1 圆角/切角形状

scss 复制代码
//圆角

val shapeModel = ShapeAppearanceModel.builder()
    .setTopLeftCorner(CornerFamily.ROUNDED, 30f) // 角度设置
    .setTopRightCorner(CornerFamily.ROUNDED, 30f)     
    .setBottomLeftCorner(CornerFamily.ROUNDED, 30f)
    .setBottomRightCorner(CornerFamily.ROUNDED, 30f).build()
binding.view1.background = MaterialShapeDrawable(shapeModel).apply {
    paintStyle = Paint.Style.FILL // 填充格式是填充内容
    fillColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
}


// 切角
val shapeModelCut =
    ShapeAppearanceModel.builder().setTopLeftCorner(CornerFamily.CUT, 30f)   // 左上圆角 30dp
        .setTopRightCorner(CornerFamily.CUT, 20f)      // 右上切角 20dp
        .setBottomLeftCorner(CornerFamily.CUT, 10f)
        .setBottomRightCorner(CornerFamily.CUT, 15f).build()
binding.view3.background = MaterialShapeDrawable(shapeModelCut).apply {
    paintStyle = Paint.Style.FILL
    fillColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
}

2.2 圆形形状

ini 复制代码
//圆形
val shapeModel2 =
    ShapeAppearanceModel.builder().setAllCornerSizes(RelativeCornerSize(0.5f)) // 左上圆角 30dp
        .build()
binding.view2.background = MaterialShapeDrawable(shapeModel2).apply {
    paintStyle = Paint.Style.FILL
    fillColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
}

2.3 其他形状

注意:

设置外部三角形状的时候需要设置 (binding.xxx.parent as ViewGroup).clipChildren = false

less 复制代码
// 外三角

val shapeModel4 =
    ShapeAppearanceModel.builder()
        .setAllCorners(RoundedCornerTreatment())
        .setAllCornerSizes(15f) // 设置圆角
        .setAllEdges(TriangleEdgeTreatment(20f, false))
        .build()
// 注意需要父布局开启
(binding.view4.parent as ViewGroup).clipChildren = false
binding.view4.background = MaterialShapeDrawable(shapeModel4).apply {
    paintStyle = Paint.Style.FILL
    fillColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
    elevation = 8f                                                    // 设置阴影高度
    initializeElevationOverlay(this@ShapeDrawableActivity)
}

// 内三角
val shapeModel5 =
    ShapeAppearanceModel.builder()
        .setAllCorners(RoundedCornerTreatment())
        .setAllCornerSizes(15f) // 设置圆角
        .setAllEdges(TriangleEdgeTreatment(20f, true))
        .build()

binding.view5.background = MaterialShapeDrawable(shapeModel5).apply {
    paintStyle = Paint.Style.FILL
    fillColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
    elevation = 8f                                                    // 设置阴影高度
    initializeElevationOverlay(this@ShapeDrawableActivity)

}

// 指定位置外三角
(binding.view6.parent as ViewGroup).clipChildren = false
val shapeModel6 =
    ShapeAppearanceModel.builder()
        .setAllCorners(RoundedCornerTreatment())
        .setAllCornerSizes(15f) // 设置圆角
        .setBottomEdge(OffsetEdgeTreatment(TriangleEdgeTreatment(20f, false), 10f))
        .build()

binding.view6.background = MaterialShapeDrawable(shapeModel6).apply {
    paintStyle = Paint.Style.FILL
    fillColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
    elevation = 8f                                                    // 设置阴影高度
    initializeElevationOverlay(this@ShapeDrawableActivity)
}

2.4 边框

less 复制代码
// 边框
val shapeModel7 = ShapeAppearanceModel.builder()
    .setAllCorners(RoundedCornerTreatment())
    .setAllCornerSizes(15f) // 设置圆角
    .setBottomEdge(OffsetEdgeTreatment(TriangleEdgeTreatment(20f, false), 10f))
    .build()
(binding.view7.parent as ViewGroup).clipChildren = false
binding.view7.background = MaterialShapeDrawable(shapeModel7).apply {
    paintStyle = Paint.Style.FILL_AND_STROKE
    strokeWidth = 3f
    fillColor =  ColorStateList.valueOf(Color.GREEN)
    strokeColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
    setTint(Color.GREEN)                                              // 设置阴影高度
    initializeElevationOverlay(this@ShapeDrawableActivity)
}

2.5 阴影

less 复制代码
// 阴影效果
val shapeModel10 = ShapeAppearanceModel.builder()
    .setAllCorners(CornerFamily.ROUNDED, 24f)
    .build()

val materialShapeDrawable = MaterialShapeDrawable(shapeModel10).apply {
    fillColor =  ColorStateList.valueOf(Color.parseColor("#FF4081")) //可以设置各个状态颜色(默认颜色、点击颜色等)
    shadowCompatibilityMode = MaterialShapeDrawable.SHADOW_COMPAT_MODE_ALWAYS //阴影兼容模式
    initializeElevationOverlay(this@ShapeDrawableActivity)
    elevation = 10f// 设置阴影高度
    setShadowColor( Color.GRAY) // 阴影颜色(半透明黑)
}
(binding.view10.parent as ViewGroup).clipChildren = false
binding.view10.apply {
    background = materialShapeDrawable
}

2.6 动态设置角度

具体效果 看gif图

ini 复制代码
// 动态设置
val shapeModelStart = ShapeAppearanceModel.builder()
    .setAllCorners(CornerFamily.ROUNDED, 0f)
    .build()
val drawable = MaterialShapeDrawable(shapeModelStart).apply {
    fillColor = ColorStateList.valueOf(Color.parseColor("#FF4081"))
    initializeElevationOverlay(this@ShapeDrawableActivity)
}
binding.view11.apply {
    background = drawable
    elevation = 0f
    clipToOutline = false
}

    // 动态圆角和阴影动画
val animator = ValueAnimator.ofFloat(0f, 48f).apply {
    duration = 2000L
    repeatMode = ValueAnimator.REVERSE
    repeatCount = ValueAnimator.INFINITE

    addUpdateListener { animation ->
        val radius = animation.animatedValue as Float

        // 动态圆角
        drawable.shapeAppearanceModel = ShapeAppearanceModel.builder()
            .setAllCorners(CornerFamily.ROUNDED, radius)
            .build()
        drawable.invalidateSelf()

        // 动态阴影,高度跟圆角同步变化(示例)
        binding.view11.elevation = (radius / 2f)
    }
}
animator.start()

3.关键说明

CornerTreatment 边角处理

  • RoundedCornerTreatment 标准圆角处理
  • CutCornerTreatment 切角(斜角)处理
  • OvalCornerTreatment 椭圆角处理

EdgeTreatment (边缘处理)

  • LineEdgeTreatment 默认直线边缘
  • MarkerEdgeTreatment 带标记(如三角形)的边缘
  • TriangleEdgeTreatment 带锯齿的边缘(多个三角形
  • OffsetEdgeTreatment 便宜现有边缘

设置外部三角形状的时候需要设置 (binding.xxx.parent as ViewGroup).clipChildren = false

总结

MaterialShapeDrawable 用来生成各种形状的纯色背景,暂不支持多颜色和背景图的形状生成,具体功能实现先到这里 ,有时间的话,分析下源码实现.

相关推荐
小趴菜82278 小时前
安卓接入Kwai广告源
android·kotlin
2501_916013748 小时前
iOS 混淆与 App Store 审核兼容性 避免被拒的策略与实战流程(iOS 混淆、ipa 加固、上架合规)
android·ios·小程序·https·uni-app·iphone·webview
程序员江同学9 小时前
Kotlin 技术月报 | 2025 年 9 月
android·kotlin
码农的小菜园10 小时前
探究ContentProvider(一)
android
时光少年11 小时前
Compose AnnotatedString实现Html样式解析
android·前端
hnlgzb12 小时前
安卓中,kotlin如何写app界面?
android·开发语言·kotlin
jzlhll12313 小时前
deepseek kotlin flow快生产者和慢消费者解决策略
android·kotlin
火柴就是我13 小时前
Android 事件分发之动态的决定某个View来处理事件
android
一直向钱13 小时前
FileProvider 配置必须针对 Android 7.0+(API 24+)做兼容
android
zh_xuan13 小时前
Android 消息循环机制
android