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

相关推荐
游戏开发爱好者81 小时前
日常开发与测试的 App 测试方法、查看设备状态、实时日志、应用数据
android·ios·小程序·https·uni-app·iphone·webview
王码码20352 小时前
Flutter for OpenHarmony 实战之基础组件:第三十一篇 Chip 系列组件 — 灵活的标签化交互
android·flutter·交互·harmonyos
黑码哥2 小时前
ViewHolder设计模式深度剖析:iOS开发者掌握Android列表性能优化的实战指南
android·ios·性能优化·跨平台开发·viewholder
亓才孓2 小时前
[JDBC]元数据
android
独行soc2 小时前
2026年渗透测试面试题总结-17(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
金融RPA机器人丨实在智能2 小时前
Android Studio开发App项目进入AI深水区:实在智能Agent引领无代码交互革命
android·人工智能·ai·android studio
科技块儿2 小时前
利用IP查询在智慧城市交通信号系统中的应用探索
android·tcp/ip·智慧城市
独行soc3 小时前
2026年渗透测试面试题总结-18(题目+回答)
android·网络·安全·web安全·渗透测试·安全狮
王码码20353 小时前
Flutter for OpenHarmony 实战之基础组件:第二十七篇 BottomSheet — 动态底部弹窗与底部栏菜单
android·flutter·harmonyos
2501_915106323 小时前
app 上架过程,安装包准备、证书与描述文件管理、安装测试、上传
android·ios·小程序·https·uni-app·iphone·webview