
Material Design 2.0 introdujo varios conceptos nuevos. Una de ellas es la atención especial a las formas geométricas de los elementos de la interfaz. Y hay una manera fácil de hacer hermosas formas personalizadas. Se llama MaterialShapeDrawable. Veamos qué tan útil y fácil es usarlo.
Hay varias formas de agregar elementos gráficos a la pantalla de una aplicación de Android. Lo más sencillo es importar mapas de bits en formato webp o png. Otra opción es usar VectorDrawable, que le permite estirar la imagen al tamaño que necesita. Otra forma de agregar gráficos a la pantalla es usar ShapeDrawable. Estas últimas son la forma más fácil de agregar un fondo simple o incluso crear un ícono. Las imágenes creadas con ShapeDrawable son independientes de la densidad de píxeles en la pantalla. Se pueden describir en un archivo xml, formar parte de otro recurso gráfico (por ejemplo, StateListDrawable) y están presentes en el SDK de Android, comenzando con API v.1.
Para cambiar la apariencia de una figura, podemos cambiar varias propiedades de ShapeDrawable: el nombre de la figura, el color de relleno (o degradado) y el color del borde de la figura. Para los rectángulos, también puede establecer el radio de las esquinas. Con estas propiedades, puede crear gráficos que se utilizarán como imágenes individuales en la pantalla, divisores, fondos de botones o para cualquier otro propósito. Si la aplicación usa la API v.21 + y ShapeDrawable como fondo para elementos con elevación, entonces la sombra debajo de estos elementos también tendrá la forma correcta:

ShapeDrawable es una herramienta práctica que casi siempre hace bien su trabajo, pero con la llegada de Material Design 2.0, los desarrolladores necesitan algo más flexible. El nuevo sistema de diseño fomenta el uso de diferentes formas para enfatizar su significado, condición y estilo de aplicación individual. Escribí anteriormente que hay varias formas de hacer lo deseado, pero la más simple ya no es relevante. ¿Significa esto que necesitamos comenzar a usar gráficos vectoriales y así perder la capacidad de "liberar" crear sombras para elementos de interfaz con elevación? ¿O vale la pena volver a usar imágenes ráster y crear recursos gráficos para seis posibles densidades de píxeles en la pantalla? Afortunadamente, con el advenimiento de Material Design 2.0, apareció una biblioteca de componentes completamente nueva.
Esta biblioteca fue creada para unificar la apariencia y el comportamiento de la interfaz de usuario de Material Design en todas las versiones de Android y otras plataformas (hay versiones de esta biblioteca para iOS, la web y para Flutter). La biblioteca de componentes implementa muchas características para el nuevo diseño de materiales. Por ejemplo, incluye el componente BottomAppBar con el comportamiento esperado. Entre otros componentes y utilidades, está la clase MaterialShapeDrawable. En mi opinión, esta es una herramienta necesaria para resolver las tareas que el nuevo sistema de diseño plantea para los desarrolladores.
Aunque MaterialShapeDrawable todavía se considera experimental en la versión 1.0.0 de la biblioteca, se puede usar para crear efectos geniales en la aplicación. En la clase MaterialShapeDrawable, puede describir una forma especificando la apariencia de sus lados y cada uno de sus ángulos. Estas propiedades especificadas pueden ser controladas por un interpolador, que les permite animar.
Para crear su propio MaterialShapeDrawable, puede usar el constructor al que necesita pasar un objeto de tipo ShapePathModel en los parámetros. Almacena información sobre cada lado y cada esquina de la figura en las clases EdgeTreatment y CornerTreatment, respectivamente (siempre hay exactamente cuatro lados y ángulos, pero esto no interfiere con la descripción de casi cualquier figura con su ayuda). Puede especificar descripciones personalmente para cada lado y esquina, o configurarlas de una vez para toda la figura llamando a un método.
La biblioteca ya tiene varias descripciones listas para usar del tratamiento de los lados y ángulos, que incluyen la mayoría de las innovaciones con respecto a la forma de los componentes introducidos en Material Design 2.0. Ya presente: RoundedCornerTreatment - para esquinas redondeadas, CutCornerTreatment - para esquinas cortadas, TriangleEdgeTreatment - para cortar o agregar un triángulo a un lado. Para demostrar su trabajo, hay un ejemplo simple:
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
Se verá así:

Por supuesto, simplemente puede crear sus propias descripciones de caras y ángulos. La forma siempre se establece para el elemento superior izquierdo, y Drawable realizará las operaciones de rotación / reflexión para obtener la forma terminada. Hay un pequeño ejemplo para demostrar esto:
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) } }
Si este MaterialShapeDrawable se usa como fondo, el resultado será así:

El paquete bottomappbar de la nueva Biblioteca de componentes de material tiene un BottomAppBarTopEdgeTreatment. Describe el recorte en BottomAppBar para el botón FloatingActionButton. Su parte superior se puede animar dependiendo de la posición y el tamaño del botón. Le aconsejo que lea el código de estas clases para ver con sus propios ojos que MaterialShapeDrawable es muy flexible de usar y que casi todo se puede hacer con él.
Si hablamos del ShapeDrawable habitual, hay otro detalle que vale la pena mencionar: la capacidad de proyectar una sombra de la forma correspondiente al contorno. Dado que ahora puede crear contornos de formas muy inusuales con MaterialShapeDrawable, sería una decepción no llevar la forma de la sombra a la forma de la imagen, especialmente cuando estas sombras se pueden ver en todas partes en Matarial Design 2.0. MaterialShapeDrawable también calcula la apariencia de la sombra. Usando la propiedad shadowEnabled, puede habilitar la sombra, que seguirá exactamente el contorno de la figura, también es posible determinar el radio, la elevación y el color de la sombra. ¿Suena demasiado bueno para ser verdad? Lamentablemente si. Si usa la sombra de MaterialShapeDrawable, obtendrá una sombra normal (dibujada por el método setShadowLayer () de la clase Paint, que fue creada para dibujar sombras en el texto), pero recortada en los bordes del componente UI en el que se muestra el resultado:

Tenga en cuenta que MaterialShapeDrawable todavía se considera experimental, como su API, y puede cambiar en el futuro. También vale la pena señalar que el código para la nueva biblioteca de Componentes de materiales está abierto, por lo que es muy bienvenido crear tickets en un rastreador de errores o incluso solicitar solicitudes para solucionar problemas conocidos. De hecho, cuando lee estas líneas, la API ya es ligeramente diferente en la rama maestra de la biblioteca (por ejemplo, se usará ShapeAppearanceModel en lugar de ShapePathModel), lo que indica trabajo activo. Una de las características prometedoras en la próxima versión puede ser la capacidad de determinar los lados / ángulos predeterminados para todo el tema de la aplicación. Puede obtener más información sobre esto en la documentación oficial o en las fuentes de la biblioteca.
Del traductor:
Es genial que haya herramientas que agreguen nuevas características al ShapeDrawable habitual y ayuden a crear no los gráficos más simples. Esto permite al desarrollador no atraer al diseñador por cada pequeña cosa, sino resolver el problema por sí mismo, y requiere mucho menos tiempo. Estamos a la espera de las próximas versiones de la biblioteca de Componentes de materiales para probar en la práctica nuevas formas de resolver problemas existentes.