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

相关推荐
summerkissyou19872 小时前
android Perfetto cpu分析教程及案例
android
消失的旧时光-19433 小时前
Android模块化架构:基于依赖注入和服务定位器的解耦方案
android·java·架构·kotlin
失重外太空啦5 小时前
Mysql练习
android·数据库·mysql
爱玩不变6 小时前
Android 升级targetSdk无法启动服务
android
用户2018792831677 小时前
“Windows大陆”安卓开发装备
android
Glacien8 小时前
compose动画全解(一)基础动画--AnimationSpec
android
Huckings8 小时前
Android车载系统时间同步方案具体实现
android·java
Kiri霧8 小时前
Kotlin重写函数中的命名参数
android·开发语言·javascript·kotlin