Creando una librería de estilos escalables en Xamarin.Forms

Contenido

En mas de una ocasión hemos utilizado o copiado los estilos de aplicaciones creadas anteriormente por ti, tu equipo o empresa a la que pertenece dentro de tu nuevo proyecto. Esto es muy normal, especialmente si los estilos creados anteriormente son una especie de obra de arte.

En mas de una ocasión nos podemos ver obligados a compartir los estilos dentro de diferentes aplicaciones. Aqui algunos motivos:

  • Estas trabajando con aplicaciones similares.
  • Las aplicaciones están bajo el mismo brand o marca.
  • las aplicaciones están relacionadas (como uber, uber driver, uber eats, etc.)
  • No quieres crear nuevos estilos, porque el que tienes ya te funciona bien.
  • Etc..

Todo esto esta muy bien, hasta que empiezas a actualizar tus estilos y tienes que modificar los mismos en cada proyecto mas tarde. Independientemente de, hoy aprenderás a crear librerías de estilos que podrás compartir entre proyectos y luego personalizar de una manera increíble.

Así que, ¡vamos a ello!

Libreria de estilos

Una librería de estilos facilita la personalización de tus diseños en tus aplicaciones para que la definición de los estilos de su marca, el soporte y y la personalización de colores, tipografía y formas sean acordes o constantes en toda la aplicación. Así podremos brindar una mejor experiencia de usuario en toda tu aplicación.

⚠ Importante

Anteriormente, te había escrito un articulo que recibió una gran acogida por la comunidad el cual titule: «Llevando el diseño de tus aplicaciones al siguiente nivel con Xamarin Forms» El cual te recomiendo que leas, si no lo has hecho.

Que necesito para crear una librería de estilos

Lo primero que vas a necesitar para crear una librería de estilos es definir como quieres estructurar o crear tus estilos. Una convención de nombres predefinida puede ayudar bastante.

1. Antes de crear nombre de estilos tienes que irte a la base. Tus estilos también estarán utilizando recursos que necesitarán ser definidos anteriormente si queremos que nuestra librería sea escalable.

💡 TIP

Un ejemplo claro, que me gusta mucho tomar de ejemplo, es la librería de Material Design que define Colores, tipografías, formas y tamaños como base y de estos nacen los estilos.

2. Una vez tienes la base definida entonces podemos proceder a crear los estilos. Como quieres que tus controles, vistas y paginas se vean y se comporten.

3. Cuando ya tienes tus estilos, solo te queda aplicarlos dentro de tus aplicaciones.

Lo que debes saber antes de crear una librería de estilos

Mas adelante, vamos a ver las formas en las que se pueden crear una librería de estilos dentro de Xamarin Forms. Pero primero vamos a refrescar algunos conceptos que hay que tener en cuenta para crear una librería de estilos.

⚠ Advertencia

El contenido y ejemplos utilizados en este articulo son con XAML. Por el momento, es la única manera de crear la base, pero igual puedes crear tus estilos CSS si así lo quieres.

⚠ Advertencia

No vamos a abundar o detallar muchos en estos conceptos. Como siempre lo mas recomendable es ir a la documentación oficial para conocer la base de los componentes de Xamarin Forms.

Estilos explícitos y estilos implícitos

Dentro de Xamarin.Forms podemos aplicar estilos de manera explicita e implícita. A modo resumen:

  • Explicito cuando debemos aplicar los estilos a elementos concretos.
  • Implícito cuando no lo aplicamos a elementos concretos, sino que asignamos solo nuestro objetivos o tipo de elementos visuales.

Vamos a ver un ejemplo:

...
            <!-- EXPLICIT -->
            <Style x:Key="labelRedStyle" TargetType="Label">
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
                <Setter Property="FontSize" Value="Large" />
                <Setter Property="TextColor" Value="Red" />
            </Style>

            <!-- IMPLICIT -->
            <Style TargetType="Entry">
                <Setter Property="HorizontalOptions" Value="Fill" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
                <Setter Property="BackgroundColor" Value="Yellow" />
                <Setter Property="FontAttributes" Value="Italic" />
                <Setter Property="TextColor" Value="Blue" />
            </Style>
...

Mas información sobre los estilos explícitos aquí, y sobre los estilos implícitos aquí.

Reemplazar estilos

No olvides que siempre puedes remplazar o modificar tus estilos. Los estilos inferiores de la jerarquía de vistas tienen prioridad sobre las definidas más arriba.

Veamos un ejemplo:

...
    <ContentPage.Resources>
        <ResourceDictionary>
            <Style x:Key="buttonStyle" TargetType="Button">
                ...
                <Setter Property="TextColor" Value="Red" />
            </Style>
        </ResourceDictionary>
    </ContentPage.Resources>

   <ContentPage.Content>
        <StackLayout Padding="0,20,0,0">
            <StackLayout.Resources>
                <ResourceDictionary>
                    <Style x:Key="buttonStyle" TargetType="Button">
                        ...
                        <Setter Property="TextColor" Value="Blue" />
                    </Style>
                </ResourceDictionary>
            </StackLayout.Resources>

            <Button Text="These buttons" Style="{StaticResource buttonStyle}" />
            <Button Text="are demonstrating" Style="{StaticResource buttonStyle}" />
            <Button Text="application style overrides" Style="{StaticResource buttonStyle}" />
        </StackLayout>
    </ContentPage.Content>
...

En este ejemplo, establecemos un estilo en nuestra pagina (estilo de nivel superior) donde se establece un botón con el texto de color rojo, pero dentro de nuestro StackLayout establecemos un estilo (estilo de nivel inferior) donde se establece un botón con el texto de color azul.

El estilo que se aplica, es el de nivel inferior. Con lo cual, el texto de los botones sera AZUL. Mas información aquí.

Herencia de estilos

La herencia de estilos nos ayudara muchísimos a crear una librería de estilos ya que nos ayudará a reutilizar, ampliar, o modificar el comportamiento de nuestros estilos.

La herencia de estilos en Xamarin Forms se utiliza estableciendo la propiedad BasedOn de nuestros en la referencia de un estilo previamente creado.

Veamos un ejemplo:

...
            <Style x:Key="baseStyle" TargetType="View">
                <Setter Property="HorizontalOptions" Value="Center" />
                <Setter Property="VerticalOptions" Value="CenterAndExpand" />
            </Style>
...
            <Style x:Key="labelStyle" TargetType="Label"
                   BasedOn="{StaticResource baseStyle}">
                ...
                <Setter Property="TextColor" Value="Teal" />
            </Style>
...

Mas información sobre la herencia de estilos aquí.

Clases de estilos

Las clases de estilos nos permiten aplicar varios estilos a un control, sin tener que recurrir a la herencia de estilos. Esto nos viene especialmente bien cuando queremos crear multiples estilos de clases que queremos compartir en un control pero quizás en otros no.

Veamos un ejemplo:

...
        <Style TargetType="BoxView" Class="Separator">
            <Setter Property="BackgroundColor" Value="#CCCCCC" />
            ...
        </Style>

        <Style TargetType="BoxView" Class="Rounded">
            <Setter Property="BackgroundColor" Value="#1FAECE" />
            ...
        </Style>    

        <Style TargetType="BoxView" Class="Circle">
            <Setter Property="BackgroundColor" Value="#1FAECE" />
            ...
            <Setter Property="CornerRadius" Value="50" />
        </Style>

        <Style TargetType="VisualElement" Class="Rotated" ApplyToDerivedTypes="true">
            <Setter Property="Rotation" Value="45" />
        </Style> 
...
...
        <BoxView StyleClass="Separator" />       
        <BoxView StyleClass="Rounded, Rotated" />
        <BoxView StyleClass="Circle" />
...

Mas información sobre las clases de estilos aquí.

Diccionarios de recursos combinados

Algo que te puede ayudar a estructurar y definir mejor tus estilos son los diccionarios de recursos, especialmente cuando los combinas.

Veamos un ejemplo:

<ContentPage ...
             xmlns:local="clr-namespace:ResourceDictionaryDemo"
             xmlns:theme="clr-namespace:MyThemes;assembly=MyThemes">
    <ContentPage.Resources>
        <ResourceDictionary>
            ...
            <ResourceDictionary.MergedDictionaries>
                ...
                <local:MyResourceDictionary />
                <theme:LightTheme />
                ...
            </ResourceDictionary.MergedDictionaries>
            ...
        </ResourceDictionary>
    </ContentPage.Resources>
    ...
</ContentPage>

Mas información sobre los estilos combinados aquí.

Estrategias para crear una librería de estilos

1. Crear librería dentro del proyecto y luego copiar en los demás

Lo mas común es tener uno o varios proyectos de donde alimentamos nuestros estilos dentro de nuevos proyectos. Y esto esta bien, hasta que ves que vas modificando/mejorando tus estilos y quieres actualizar los estilos en todos los proyectos.

Muchas veces, hasta puede ser un poco confuso recordar donde esta específicamente lo que estas buscando y nos hace perder un poco de tiempo en el proceso.

ℹ Importante

Se que el copy/paste es legendario, pero si quieres saber como crear librería de estilos escalables sigue leyendo.

2. Crear una librería de estilos en un proyecto compartido

El siguiente paso, como comprenderéis, es crear un proyecto compartido y dentro de este poner todas tus estilos o diccionarios de recursos. Una vez tienes tu librería de estilos compartido, el siguiente paso es combinar nuestros estilos dentro de nuestro nuevo proyecto.

Y con esto, ya estaría, tendrías todos tus estilos combinados dentro del nuevo proyecto.

💡 TIP

Recuerda que siempre puedes remplazar estilos utilizando los mismos nombres de nuestros recursos como vimos anteriormente. Con esto puedes adaptar tus estilos a nuevos proyectos.

Hasta aquí, siguiendo buenas practicas, todo estaría bien la verdad. Pero tenemos el detalle de que tenemos que saber cuales son los estilos que tenemos que configurar, crearlos, y luego adaptarlos a nuestro proyecto.

En la mayoría de los casos, esto no seria un problema pero si quieres crear una librería que se pueda escalar aun mas, sigue leyendo.

3. Crear una librería de estilos que pueda ser configurada entre proyectos

Hay que me gusto mucho de la librería de XF-Material-Library fue la forma en la que manejan y configuran sus recursos. Esta librería tiene dos cosas que me encantan que son: la estructura de material design y la forma en la configuran sus recursos.

Veamos un ejemplo:

...
    <Application.Resources>
        ...
        <mtrl:MaterialColorConfiguration x:Key="Material.Color"
            Background="#EAEAEA"
            Error="#B00020"
            OnBackground="#000000"
            OnError="#FFFFFF"
            OnPrimary="#FFFFFF"
            OnSecondary="#FFFFFF"
            OnSurface="#000000"
            Primary="#011A27"
            PrimaryVariant="#000000"
            Secondary="#063852"
            SecondaryVariant="#001229"
            Surface="#FFFFFF" />
        ...
    </Application.Resources>
...

Como pueden ver ellos crean un objeto donde pasamos todas nuestras configuraciones para luego agregarlos o combinarlos a los estilos que utiliza el proyecto.

Con esto, de manera muy fácil evitamos errores de typo y el mismo tiempo mantenemos nuestra librería compartida de manera muy limpia y escalable. Y claro, tenemos todas las ventajas anteriores en caso de ser necesario.

Como crear una librería de estilos que pueda ser configurada entre proyectos

Lo primero que tenemos que hacer es crear nuestros archivos de configuración, que no son mas que clases que derivan de BindableObject y tienen todas las propiedades de configuración que vamos a estar utilizando.

Veamos un ejemplo:

...
   public sealed class ColorConfiguration : BindableObject
   {
        ...
        public static readonly BindableProperty BackgroundProperty = BindableProperty.Create(nameof(Background), typeof(Color), typeof(Color), Color.FromHex("#EAEAEA"));

        public Color Background
        {
            get => (Color)GetValue(BackgroundProperty);
            set => SetValue(BackgroundProperty, value);
        }
        ...
    }
...

Tambien debes agregar una clase de configuracion que tenga todas las configuraciones de tus estilos. Veamos un ejemplo:

...
   public sealed class StyleConfiguration : BindableObject
   {
        ...
        public static readonly BindableProperty ColorConfigurationProperty = BindableProperty.Create(nameof(ColorConfiguration), typeof(ColorConfiguration), typeof(ColorConfiguration));

        public ColorConfiguration ColorConfiguration
        {
            get => (ColorConfiguration)GetValue(BackgroundProperty);
            set => SetValue(BackgroundProperty, value);
        }
        ...
    }
...

Una vez tienes tu archivo de configuración, el siguiente paso es crear tu diccionario de recursos donde vas a agregar tus recursos.

Veamos un ejemplo:

...
    public partial class Colors : ResourceDictionary
    {
       internal Colors(ColorConfiguration colorConfiguration)
       {
            Add("BackgroundColor", colorConfiguration.Background);
       }
    }
...

Una vez tienes tus diccionario de recursos para las configuraciones, el siguiente paso es crear los estilos que estaremos utilizando en el proyecto.

<ResourceDictionary ... >
    ...
    <Style Class="H1" TargetType="Label">
        ...
    </Style>
    ...
</ResourceDictionary>

Pues bien, hasta aquí todo excelentemente bien. Solo nos faltaría un mecanismo para combinar los estilos. Vemos un ejemplo:

...
    public class ProjectStyle
    {
        private ResourceDictionary _resources;

        internal ProjectStyle(Application app, StyleConfiguration config = null)
        {
            app.Resources.MergedDictionaries.Add(new Colors(config.ColorConfiguration));
            
            // MERGE YOUR PREDEFINED STYLES HERE
            app.Resources.MergedDictionaries.Add(new MyStyle());
        }

        public static void Init(Application app, StyleConfiguration config)
        {
            new ProjectStyle(app, config);
        }
...

Una vez tenemos nuestra clase de iniciación completada, solo tenemos que inicializar nuestros estilos. Veamos el ejemplo:

...
    <Application.Resources>
        ...
        <st:ColorConfiguration x:Key="Style.Color" Background="#EAEAEA" />
        <st:MaterialConfiguration x:Key="Style.Configuration" ColorConfiguration="{StaticResource Style.Color}"  />
        ...
    </Application.Resources>
...

💡 TIP

Tambien puedes inicializar estos objetos en tu archivo App.xaml.cs

...
    public partial class App : Application
    {
        public App()
        {
            InitializeComponent();
            ProjectStyle.Init(this); // Use default styles

            MainPage = new MainPage();
        }
...

Y con esto ya tendríamos nuestra librería de estilos completada y configurada para utilizarse en cualquier proyecto.

Bueno, te dejo un ejemplo con una implementación un poco mas definida basada en la librería de XF-Material-Library. Desbloquea el contenido debajo para acceder al repo de ejemplo. ⬇⬇⬇

Conclusión

Como pudiste ver, aqui te he dajado algunas estrategias para crear una libreria de estilos que puedes utilizar entre proyectos de la forma en la creas que se adapte mejor a tus necesidades.

Espero que este articulo de sea de utilidad, y nada déjenme saber en las redes que realmente les gusta este tipo de artículos y yo hare lo posible por darles lo mejor de lo mejor.

Sin nada mas que agregar, ¡Nos vemos en la próxima!

¿Qué opinas de este contenido?
 
Luis Matos

Luis Matos

I help professionals and companies to create value solutions. I am a Systems Engineer, blockchain executive, and international mobile application speaker. Founder of the Malla Consulting Agency and several international technology communities.
Suscribirte
Notificar de
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x

Buscar en el sitio