[Xamarin.Forms] App Themes

Temas

Los dispositivos móviles incluyen la opción de usar un tema claro u oscuro a nivel de sistema operativo. Las aplicaciones pueden detectar y responder al cambio del tema del sistema.

NOTA: El tema del sistema puede cambiar por diversos motivos dependiendo de la la configuración del dispositivo. Además de la elección explícita por parte del usuario, puede cambiar en base a factores ambientales como un nivel bajo de luz.

En Xamarin.Forms 4.6 se añade AppTheme. Ahora las aplicaciones de Xamarin. Forms pueden responder a los cambios de tema usado por el sistema y en este artículo vamos a ver como hacerlo.

Definir y utilizar recursos por tema

Utilizando AppThemeColor podemos definir un color para los temas del sistema Light y Dark.

<AppThemeColor x:Key="ThemeColor" Light="DarkRed" Dark="LightPink" />

Podemos usar el color como hemos estado haciendo hasta ahora:

<Label 
     Text="AppTheme Color"
     TextColor="{DynamicResource ThemeColor}"/>

De forma automática se aplicará el color rojo oscuro usando el tema claro, y rosa claro al usar el oscuro. También podemos definir un AppThemeColor usando estilos utilizando la extensión de marcado OnAppTheme:

<Style x:Key="OSThemeStyle" TargetType="Label" >
     <Setter Property="TextColor" Value="{OnAppTheme Black, Light=DarkRed, Dark=LightPink}" />
</Style>

Aplicamos el estilo:

<Label 
     Text="Using Style"
     Style="{DynamicResource OSThemeStyle}"/>

Detectar el tema actual usado por el sistema

Podemos saber el tema usado por el sistema utilizando la propiedad Application.RequestedTheme:

OSAppTheme currentTheme = Application.Current.RequestedTheme;

Obtenemos un valor de tipo enumeración OSAppTheme. La enumeración puede tener uno de los siguientes valores:

  • Unspecified, que indica que el dispositivo está utilizando un tema no especificado.
  • Light, que indica que el dispositivo está usando el tema claro.
  • Dark, que indica que el dispositivo está usando el tema oscuro.

Reaccionar al cambio de tema

El tema usado por el puede cambiar y desde nuestra aplicación, podemos detectar el cambio. Para detectar el cambio de tema podemos usar el evento Application.RequestedThemeChanged:

Application.Current.RequestedThemeChanged += (s, a) =>
{
     AppTheme requestedTheme = a.RequestedTheme;
};

Puedes encontrar un ejemplo de AppTheme en GitHub:

Ver GitHub

¿Qué te parece esta nueva API?. Recuerda, puedes dejar un comentario con cualquier pregunta o duda!.

Más información

[Tips and Tricks] RequestTheme, cambiar el tema al vuelo!

ColorIntroducción

En Windows Phone, podemos definir un tema totalmente personalizado para nuestras aplicaciones. Por defecto, ya contamos con dos temas, claro y oscuro (“Light” y “Dark” respectivamente). Si no usamos nuestro propio tema totalmente personalizado debemos gestionar los elementos de nuestra interfaz para una correcta visualización tanto en el tema claro como en el oscuro. El usuario puede cambiar el tema a utilizar (por defecto oscuro).

Podemos forzar el utilizar un tema en concreto e incluso en tiempo de ejecución podemos modificar el tema a utilizar para cualquier elemento.

NOTA: Modificar la propiedad Application.RequestedTheme en tiempo de ejecución provoca una excepción.

RequestTheme

La propiedad RequestedTheme nos permite obtener o establecer el tema a utilizar. Al cambiar el valor de RequestedTheme de la Aplicación a nivel general o de un elemento en concreto provoca que se obtengan las plantillas y estilos del ResourceDictionary denominados “Light” o “Dark” de la colección ThemeDictionaries.

NOTA: La propiedad RequestedTheme es ignorada si el usuario tiene activo el modo de alto contraste.

Crearemos un ejemplo muy simple para realizar el cambio en tiempo de ejecución del tema. Creamos dos sencillos botones:

<Button Content="Light" />
<Button Content="Dark" />

El primero cambiara al tema claro y el segundo al tema oscuro:

Nuestra UI en el tema por defecto

Nuestra UI en el tema por defecto

En nuestra viewmodel, contaremos con un comando para cada botón:

private ICommand _lightCommand;
private ICommand _darkCommand;

public ICommand LightCommand
{
     get { return _lightCommand = _lightCommand ?? new DelegateCommand(LightCommandExecute); }
}

public ICommand DarkCommand
{
     get { return _darkCommand = _darkCommand ?? new DelegateCommand(DarkCommandExecute); }
}

private void LightCommandExecute()
{

}

private void DarkCommandExecute()
{

}

La definición de los botones quedara:

<Button Content="Light" Command="{Binding LightCommand}" />
<Button Content="Dark" Command="{Binding DarkCommand}" />

En Windows Phone 8.1, la App cuenta con una Window que contiene un único Frame que ocupa el 100% del área de la pantalla.

El Frame de la Aplicación

El Frame de la Aplicación

El Frame, se crea en el arranque de la aplicación y es el encargado de contener y gestionar cada una de las páginas (Page). La propiedad RequestedTheme establecida en un elemento FrameworkElement es heredado en sus elementos hijos. Podemos anular la herencia estableciendo la propiedad RequestedTheme en un elemento hijo concreto. Estableceremos la propiedad en el Frame de la Aplicación provocando que la misma sea heredada por sus elementos hijos, es decir, las páginas de la Aplicación:

AppFrame.RequestedTheme = ElementTheme.Light;

En el segundo comando establecemos el RequestedTheme del Frame de la Aplicación al tema oscuro:

AppFrame.RequestedTheme = ElementTheme.Dark;

Al cambiar al tema claro nuestra interfaz se vera de la siguiente forma:

Cambio de tema a claro

Cambio de tema a claro

El resultado en video:

Podéis descargar el pequeño ejemplo realizado a continuación:

Más información

[Tips and Tricks] Temas personalizados en Windows Phone

Accent-ColorsIntroducción

Al crear aplicaciones, un punto importante en el proceso creativo es la elección de colores y estilos de la misma. En determinadas ocasiones estaremos creando algo nuevo y la selección será bajo nuestro criterio mientras que en otras ocasiones estaremos realizando una aplicación para una marca ya establecida en cuyo caso debemos crear una aplicación que se adapte al esquema de colores ya seleccionados por la marca.

Problema

Si por marca decidimos que los colores adecuados para nuestra aplicación siempre serán el naranja junto al fondo claro por ejemplo, puede ser que no siempre el usuario obtenga el resultado que nosotros esperamos. El usuario puede cambiar el tema del sistema afectando a fondos, bordes y colores de fuentes de múltiples controles y por lo tanto a nuestra aplicación.

¿Solución?

Como suele ser habitual tenemos varias opciones para resolver el problema. La primera de ellas consiste en crearnos un conjunto de estilos sobreescribiendo los establecidos por defecto. Podemos dirigirnos a la ruta:

C:\Program Files (x86)\Microsoft SDKs\Windows Phone\v8.0\Design

Seleccionamos el tema Light o Dark según se adapte más a nuestras necesidades y partiendo de esa base crear nuestro propio estilo que añadiremos como recurso. Esta solución aunque válida requiere un esfuerzo elevado.

Tenemos una segunda opción que nos permite resolver en problema con un par de líneas. Interesante, ¿verdad?.

Utilizaremos para ello una librería creada por Jeff Wilcox llamada Windows Phone Theme Manager. Tenéis la librería disponible como paquete NuGet y también acceso al código fuente desde GitHub.

Ya sea obteniendo el paquete desde NuGet o desde GitHub, su uso es simple, en el constructor de la aplicación:

/// <summary>
/// Constructor.
/// </summary>
public App()
{
     // Global handler for uncaught exceptions.
     UnhandledException += Application_UnhandledException;

     // Standard Silverlight initialization
     InitializeComponent();

     // Phone-specific initialization
     InitializePhoneApplication();

     //More code here...
}

Añadiremos la siguiente línea para forzar el tema claro:

ThemeManager.ToLightTheme();

O el tema oscuro:

ThemeManager.ToDarkTheme();

NOTA: Si forzamos un tema ha de hacerse una única vez y desde el constructor de App.cs tras las llamadas de inicialización.

O incluso podemos utilizar temas personalizados con suma facilidad. Añadimos un conjunto de recursos (ThemeResource.xaml) con todos los estilos personalizados que necesitemos al proyecto. Para tener acceso  los recursos, en App.xaml los añadimos al MergeDictionary. Una vez realizado, utilizarlo sería tan sencillo como:

// Obtenemos el tema
var rd = App.Current.Resources.MergedDictionaries.First();

// Establecemos el tema
ThemeManager.SetCustomTheme(rd, Theme.Light);

De esta forma tan simple podemos forzar a nuestra aplicación a utilizar siempre el tema claro o el oscuro. O incluso utilizar un conjunto de estilos junto al tema claro u oscuro.

Más información