如何使用MaterialShapeDrawable创建自定义形状

图片

Material Design 2.0引入了几个新概念。 其中之一是特别注意界面元素的几何形式。 并且有一种简单的方法可以制作漂亮的自定义形状。 它称为MaterialShapeDrawable。 让我们看看它的实用性和简便性。


有几种方法可以将图形元素添加到Android应用程序的屏幕。 最简单的方法是以webp或png格式导入位图。 另一个选择是使用VectorDrawable,它允许您将图像拉伸到所需的大小。 将图形添加到屏幕的另一种方法是使用ShapeDrawable。 后者是添加简单背景甚至创建图标的最简单方法。 使用ShapeDrawable创建的图像与屏幕上的像素密度无关。 它们可以在xml文件中描述,可以是另一个图形资源(例如StateListDrawable)的一部分,并且可以从API v.1开始存在于Android SDK中。


要更改图形的外观,我们可以更改几个ShapeDrawable属性:图形的名称,填充颜色(或渐变)和图形的边框颜色。 对于矩形,您还可以设置角的半径。 使用这些属性,您可以创建图形,这些图形将用作屏幕上的单个图像,分隔线,按钮背景或用于任何其他目的。 如果应用程序使用API​​ v.21 +和ShapeDrawable作为具有高程的元素的背景,则这些元素下的阴影也将具有正确的形状:


图片


ShapeDrawable是一种方便的工具,几乎总是可以很好地完成其工作,但是随着Material Design 2.0的出现,开发人员需要更加灵活的工具。 新的设计系统鼓励使用不同的形式来强调其含义,条件和个人应用风格。 我在上面写道,有几种方法可以实现所需的目标,但是其中最简单的目标已不再适用。 这是否意味着我们需要开始使用矢量图形,从而失去为带有高程的界面元素“自由”创建阴影的能力? 还是值得回退到使用光栅图像并为屏幕上的六个可能像素密度创建图形资源? 幸运的是,随着Material Design 2.0的出现,一个全新的组件库已经出现。


创建该库是为了统一Material Design UI组件在所有版本的Android和其他平台上的外观和行为(该库有iOS,Web和Flutter的版本)。 零部件库为新的材料设计实现了许多功能。 例如,它包括具有预期行为的BottomAppBar组件。 在其他组件和实用程序中,有MaterialShapeDrawable类。 我认为,这是解决新设计系统对开发人员提出的任务的必要工具。


尽管MaterialShapeDrawable在1.0.0库版本中仍被认为是实验性的,但可用于在应用程序中创建炫酷效果。 在MaterialShapeDrawable类中,您可以通过指定形状的侧面和每个角度来描述形状。 这些指定的属性可以由内插器控制,从而允许它们进行动画处理。


要创建自己的MaterialShapeDrawable,可以使用需要在参数中传递ShapePathModel类型的对象的构造函数。 它分别在EdgeTreatment和CornerTreatment类中存储有关图形的每个边和每个角的信息(总是正好有四个侧面和角度,但这几乎不影响借助它们描述任何图形)。 您可以亲自为每个边和角指定描述,或者通过调用一个方法一次为整个图形设置一次。


该库已经有关于边和角的处理的几个现成的描述,其中包括有关Material Design 2.0中引入的组件形状的大多数创新。 已经存在:RoundedCornerTreatment-用于圆角,CutCornerTreatment-用于切角,TriangleEdgeTreatment-在侧面切割或添加三角形。 为了演示他们的工作,有一个简单的示例:


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 

它看起来像这样:


图片


当然,您可以简单地创建自己的面和角度描述。 始终为左上方的元素设置形状,而Drawable将执行旋转/反射操作以获得最终形状。 有一个小例子来说明这一点:


 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) } } 

如果将此MaterialShapeDrawable用作背景,则结果将如下所示:


图片


新材料组件库的bottomappbar程序包具有BottomAppBarTopEdgeTreatment。 它在BottomAppBar中描述了FloatingActionButton按钮的切口。 可以根据按钮的位置和大小为其上侧设置动画。 我建议您阅读这些类的代码,以便亲眼看到MaterialShapeDrawable的使用非常灵活,几乎所有事情都可以使用它完成。


如果我们谈论通常的ShapeDrawable,还有另一个值得一提的细节-投射与轮廓对应的形状阴影的能力。 由于您现在可以使用MaterialShapeDrawable创建非常不寻常的形状的轮廓,因此不要将阴影的形状带入图像的形状令人失望,尤其是当这些阴影在Matarial Design 2.0中随处可见时。 MaterialShapeDrawable也可以计算阴影的外观。 使用shadowEnabled属性,您可以启用阴影,该阴影将完全遵循图形本身的轮廓,还可以确定阴影的半径,高程和颜色。 听起来好得令人难以置信? 不幸的是。 如果使用MaterialShapeDrawable的阴影,则会得到一个普通的阴影(由Paint类的setShadowLayer()方法绘制,该方法是在文本上绘制阴影的),但会裁剪到显示结果的UI组件的边界:


图片


请记住,与它的API一样,MaterialShapeDrawable仍被视为实验性的,并且将来可能会更改。 还值得注意的是,新的Material Components库的代码是开放的,因此非常欢迎在Bug跟踪器中创建票证,甚至提出具有修复已知问题的请求。 实际上,当您阅读这些行时,该库的master分支中的API已经稍有不同(例如,将使用ShapeAppearanceModel代替ShapePathModel),这表明工作正在进行中。 下一个版本中有希望的功能之一可能是能够确定整个应用程序主题的默认边/角度。 您可以从官方文档或库资源中了解更多信息。


来自翻译者:
很酷,有些工具可以向通常的ShapeDrawable添加新功能,并且可以帮助创建最简单的图形。 这样一来,开发人员就不必为每件小事拉扯设计师,而是自己解决问题,并且所需时间大大减少。 我们正在等待材料组件库的下一个版本尝试实践解决现有问题的新方法。

Source: https://habr.com/ru/post/zh-CN426997/


All Articles