Esto articulo nace a partir de una pregunta en StackOverflow, normalmente yo entro al finalizar mi día a esta página de preguntas y respuesta donde de vez en cuando doy algunas sugerencias.
Hace unos días surgió una pregunta por un usuario en este portal, básicamente la ayuda que necesitaba era que quería saber cómo personalizar el NavigationBar de una aplicación Xamarin.Forms para Android y iOS. Este control también es conocido como AppBar en Android y UINavigationBar en iOS y este usuario necesitaba que quede de esta manera:
Lo primero que se nos debe venir a la mente cuando queremos personalizar un control en Xamarin.Forms es usar los Custom Renderers, esto te permite cambiar la apariencia y el comportamiento de los controles en cada plataforma.
Recuerda que las interfaces de usuario en Xamarin.Forms se representan con los controles nativos de la plataforma de destino, lo que permite que las aplicaciones de Xamarin.Forms conserven el aspecto para cada plataforma.
Los Custom Renderers permiten a los desarrolladores anular este proceso para personalizar el aspecto y el comportamiento de los controles de Xamarin.Forms en cada plataforma.
Bueno ahora que ya sabes algo básico acerca de los Custom Renderers es hora de aprender cómo se utilizan y que fue lo que hice para solucionar el problema de este usuario.
Manos a la obra
Lo primero que tenemos que hacer es crear una clase para este ejemplo le pondremos NavigationPageGradientHeader, esta clase que nosotros creamos tendrá que extender del control que queramos personalizar, en mi caso extenderá del control NavigationPage.
Ahora crearemos las BindableProperties que serán las encargadas de hacer Binding a los valores que nosotros referenciemos, un BindableProperty tiene la siguiente estructura:
propertyName: Es la propiedad a la cual hará referencia para asignar o retornar algún valor. En mi caso yo tengo dos propiedades una llamada RightColor que será el color con el cual comenzará el gradiente y LeftRight con el cual terminará.
returnType: Será el tipo de dato que retornará está propiedad, en nuestro caso será un tipo de la clase Xamarin.Forms.Color, pero si estás necesitas retornar cualquier otro tipo de dato puedes hacerlo.
declaringType: Es la clase donde se está declarando esta BindableProperty en este caso será la misma clase donde estamos, pero podemos declarar BindableProperties fuera de la clase y referenciarla por su nombre.
defaultValue: Es el valor por defecto que tendrá nuestra BindableProperty, como nuestro tipo de dato de retorno es de tipo Color, nuestro valor por defecto tendrá que ser del mismo tipo de dato. En mi caso le puse Red.
Ahora creamos las propiedades que harán referencia nuestra BindableProperty ya sea para asignar u obtener el valor de esa propiedad.
Finalmente, nuestra clase queda de la siguiente manera:
Personalizando el control según la plataforma
Como te comenté líneas arriba un Custom Renderer permite cambiar la apariencia y el comportamiento de los controles en cada plataforma, este ejemplo está destinado solo para Android y iOS. No lo he hecho para UWP por dos razones, dejé de desarrollar hace mucho para UWP y no conozco mucho sus APIs y debido al primer motivo no sé ni por dónde empezar para personalizar el NavigationBar en UWP.
Ustedes pueden colaborar haciendo este que control personalizado soporte UWP enviando algún pull request al repositorio de Github.
Android
En Android es un tanto tedioso cambiar el control ActionBar, debido a que desde algunas actualizaciones la clase MainActivity extiende de FormsAppCompatActivity y esto de por sí ya tiene una propiedad llamada ToolbarResource la cual hace el típico SetActionBar() entonces crear una clase Renderer que extienda de PageRenderer sería inútil ya que no veríamos ningún cambio.
Para esto debemos crear un drawable llamado grandient.xml donde pondremos un shape que tenga el grandiente, este drawable tendrá la siguiente estructura:
Ahora solo en nuestro archivo Toolbar.axml ubicado en la carpeta layout haremos referencia a este drawable, finalmente nuestro Toolbar que de la siguiente manera:
Esto hará que nuestro ActionBar en Android se vea de esta forma:
iOS
En iOS es diferente y sí funciona lo de agregar un Renderer que extienda de PageRenderer en esta clase lo que haremos es crear un GradientLayer que será el que dará el efecto de gradiente a nuestro NavigationBar.
A este GradientLayer le vamos asignar los colores que serán asignados en nuestra PCL, para esto convertimos la propiedad Element en un objeto de nuestra clase principal y luego de eso solo llamamos a las propiedades correspondientes en nuestro caso RightColor y LeftColor. Recuerda que estás propiedades son del tipo de dato Xamarin.Forms.Color y el GradientLayer recibe el tipo CGColor, lo único que tenemos que hacer es invocar al método ToCGColor(), así de fácil podemos convertir nuestro tipo de dato de Xamarin.Forms a la plataforma nativa. Xamarin es maravilloso!
Ahora convertimos este GradientLayer a imagen y asignamos esta imagen a nuestro NavigationBar.
Esto hará que nuestro UINavigationBar se vea de esta forma:
Proyecto compartido
Debido a que este es un control que extiende de NavigationPage nosotros debemos de invocar a este control en nuestro archivo App.xaml.cs:
Conclusión
Bueno, este es un micro post que nació de una pregunta en StackOverflow, te expliqué un concepto básico de los Custom Renderers y como es la implementación en cada plataforma.
Recuerda que el código de este ejemplo está en mi repositorio de Github.
Además la pregunta de StackOverflow que hago referencia en este articulo la puedes encontrar aquí:
How to Add a Gradient in Xamarin forms Toolbar and UINavigationBar