阅读 1330

Android Material MaterialShapeDrawable

1. 使用

项目中遇到一个需求,一段文字的背景是类似于对话框那样带有箭头,如图:

刚开始的想法是通过Tooltip库展示,但是由于箭头位置需要自定义,作者没有提供入口。后根据该库中提供的TooltipTextDrawable,想到自定义Drawable,偶然发现material包中提供了TooltipDrawable,但是不允许外部使用,代码如下:

@RestrictTo(LIBRARY_GROUP)
public class TooltipDrawable extends MaterialShapeDrawable implements TextDrawableDelegate
复制代码

但是该类的父类MaterialShapeDrawable是可以使用的,经过查询资料发现使用很简单,也不用自定义Drawable,也不用额外导入库。故记录一下用法。

 val appearanceModel = ShapeAppearanceModel.builder()
 	.setAllCornerSizes(DisplayUtils.dp2pxF(6F))
    .setBottomEdge(OffsetEdgeTreatment(
    	TriangleEdgeTreatment(DisplayUtils.dp2pxF(6F), false),
        DisplayUtils.dp2pxF(10F)))
     .build()

 val drawable = MaterialShapeDrawable(appearanceModel).apply {
 	setTint(Color.parseColor("#FA4B05"))
    paintStyle = Paint.Style.FILL
 }

 tv_tip.background = drawable
复制代码

创建MaterialShapeDrawable对象,构造方法需要传入ShapeAppearanceModel参数,通过ShapeAppearanceModel可以设置各个角、各个边的效果,这些效果通过各种treatment实现。

2. 样式

已有的各种treatment如下:

  • CornerTreatment
    • RoundedCornerTreatment 圆角方案
    • CutCornerTreatment 折角方案
  • EdgeTreatment
    • TriangleEdgeTreatment 三角形
    • MarkerEdgeTreatment 类似于地图的兴趣点
    • OffsetEdgeTreatment 位移
    • BottomAppBarTopEdgeTreatment 应该是中间带有悬浮按钮的效果

效果一

val shapePathModel = ShapePathModel().apply {
    setAllCorners(CutCornerTreatment(dip(5).toFloat()))
    setAllEdges(TriangleEdgeTreatment(dip(5).toFloat(), true))
}
val backgroundDrawable = MaterialShapeDrawable(shapePathModel).apply {
    setTint(ContextCompat.getColor(this@MainActivity, R.color.colorPrimary))
    paintStyle = Paint.Style.FILL
}
textView.background = backgroundDrawable
复制代码

效果二

class CutoutCornersTreatment(val size: Float) : CornerTreatment() {
    override fun getCornerPath(angle: Float, interpolation: Float, shapePath: ShapePath) {
        shapePath.reset(0.0f, size * interpolation)
        shapePath.lineTo(size * interpolation, size * interpolation)
        shapePath.lineTo(size * interpolation, 0f)
    }
}
class CurvedEdgeTreatment(val size: Float) : EdgeTreatment() {
    override fun getEdgePath(length: Float, interpolation: Float, shapePath: ShapePath) {
        shapePath.quadToPoint(length / 2f, size * interpolation, length, 0f)
    }
}
复制代码

以上两种效果引用自参考文章2

3. 遇到的问题

在使用中遇到一个问题,箭头向内有效果,但是箭头向下竟然没有效果,经查询需要在应用drawable的父类中增加如下参数:

android:clipChildren="false"
android:clipToPadding="false"
复制代码

4. 大佬的demo

github.com/VolodyaVech…

5. 参考文章

  1. medium.com/ackee/creat…
  2. stackoverflow.com/questions/6…
文章分类
Android
文章标签