Responder a los cambios del tema del sistema en las aplicaciones de Xamarin.Forms

Download SampleDescargar el ejemplo

Los dispositivos suelen incluir temas claros y oscuros, que hacen referencia a un amplio conjunto de preferencias de apariencia que se pueden configurar a nivel de sistema operativo. Las aplicaciones deben respetar estos temas del sistema y responder inmediatamente cuando cambia el tema del sistema.

El tema del sistema puede cambiar por diversos motivos, en función de la configuración del dispositivo. Por ejemplo, cuando el usuario cambia explícitamente el tema del sistema y cuando el tema cambia debido a la hora del día y a factores ambientales como luz escasa.

Las aplicaciones de Xamarin.Forms pueden responder a los cambios de tema del sistema mediante el consumo de recursos con la extensión de marcado AppThemeBinding y los métodos de extensión SetAppThemeColor y SetOnAppTheme<T>.

Se deben cumplir los siguientes requisitos para que Xamarin.Forms responda a un cambio de tema del sistema:

  • Xamarin.Forms 4.6.0.967 o posterior.
  • iOS 13 o posterior.
  • Android 10 (API 29) o posterior.
  • Compilación 14393 o posterior de UWP.
  • macOS 10.14 o posterior.

En las capturas de pantalla siguientes se muestran páginas con temas, para los temas de sistema claro y oscuro en iOS y Android:

Screenshot of the main page of a themed app, on iOS and AndroidScreenshot of the detail page of a themed app, on iOS and Android

Definir y consumir recursos de tema

Los recursos para temas claros y oscuros se pueden consumir con la extensión de marcado AppThemeBinding y los métodos de extensión SetAppThemeColor y SetOnAppTheme<T>. Con estos enfoques, los recursos se aplican automáticamente en función del valor del tema del sistema actual. Además, los objetos que consumen estos recursos se actualizan automáticamente si el tema del sistema cambia mientras se ejecuta una aplicación.

AppThemeBinding (extensión de marcado)

La extensión de marcado AppThemeBinding permite consumir un recurso, como una imagen o un color, en función del tema del sistema actual:

<ContentPage ...>
    <StackLayout Margin="20">
        <Label Text="This text is green in light mode, and red in dark mode."
               TextColor="{AppThemeBinding Light=Green, Dark=Red}" />
        <Image Source="{AppThemeBinding Light=lightlogo.png, Dark=darklogo.png}" />
    </StackLayout>
</ContentPage>

En este ejemplo, el color de texto del primer Label se establece en verde cuando el dispositivo usa su tema claro y se establece en rojo cuando el dispositivo usa su tema oscuro. Del mismo modo, el Image muestra un archivo de imagen diferente basado en el tema del sistema actual.

Además, los recursos definidos en un ResourceDictionary se pueden usar con la extensión de marcado StaticResource:

<ContentPage ...>
    <ContentPage.Resources>

        <!-- Light colors -->
        <Color x:Key="LightPrimaryColor">WhiteSmoke</Color>
        <Color x:Key="LightSecondaryColor">Black</Color>

        <!-- Dark colors -->
        <Color x:Key="DarkPrimaryColor">Teal</Color>
        <Color x:Key="DarkSecondaryColor">White</Color>

        <Style x:Key="ButtonStyle"
               TargetType="Button">
            <Setter Property="BackgroundColor"
                    Value="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}" />
            <Setter Property="TextColor"
                    Value="{AppThemeBinding Light={StaticResource LightSecondaryColor}, Dark={StaticResource DarkSecondaryColor}}" />
        </Style>

    </ContentPage.Resources>

    <Grid BackgroundColor="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}">
      <Button Text="MORE INFO"
              Style="{StaticResource ButtonStyle}" />
    </Grid>    
</ContentPage>    

En este ejemplo, el color de fondo de Grid y el estilo Button cambia en función de si el dispositivo usa su tema claro o tema oscuro.

Para obtener más información sobre la extensión de marcado AppThemeBinding, consulte Extensión de marcado AppThemeBinding.

Métodos de extensión

Xamarin.Forms incluye los métodos de extensión SetAppThemeColor y SetOnAppTheme<T> que permiten a los objetos VisualElement responder a los cambios de tema del sistema.

El método SetAppThemeColor permite especificar objetos Color que se establecerán en una propiedad de destino en función del tema del sistema actual:

Label label = new Label();
label.SetAppThemeColor(Label.TextColorProperty, Color.Green, Color.Red);

En este ejemplo, el color de texto de Label se establece en verde cuando el dispositivo usa su tema claro y se establece en rojo cuando el dispositivo usa su tema oscuro.

El método SetOnAppTheme<T> permite especificar objetos de tipo T que se establecerán en una propiedad de destino en función del tema del sistema actual:

Image image = new Image();
image.SetOnAppTheme<FileImageSource>(Image.SourceProperty, "lightlogo.png", "darklogo.png");

En este ejemplo, Image muestra lightlogo.png cuando el dispositivo usa su tema claro y darklogo.png cuando el dispositivo usa su tema oscuro.

Detectar el tema del sistema actual

El tema del sistema actual se puede detectar obteniendo el valor de la propiedad Application.RequestedTheme:

OSAppTheme currentTheme = Application.Current.RequestedTheme;

La propiedad RequestedTheme devuelve un miembro de enumeración OSAppTheme. La enumeración OSAppTheme define los miembros siguientes:

  • Unspecified, que indica que el dispositivo usa un tema no especificado.
  • Light, que indica que el dispositivo usa su tema claro.
  • Dark, que indica que el dispositivo usa su tema oscuro.

Establecer el tema de usuario actual

El tema usado por la aplicación se puede establecer con la propiedad Application.UserAppTheme, que es de tipo OSAppTheme, independientemente del tema del sistema que esté operativo actualmente:

Application.Current.UserAppTheme = OSAppTheme.Dark;

En este ejemplo, la aplicación se establece para usar el tema definido para el modo oscuro del sistema, independientemente del tema del sistema que esté operativo actualmente.

Nota:

Establece la propiedad UserAppTheme en OSAppTheme.Unspecified para que sea el tema del sistema operativo predeterminado.

Reacción a los cambios de temas

El tema del sistema en un dispositivo puede cambiar por diversos motivos, en función de cómo se configure el dispositivo. Las aplicaciones de Xamarin.Forms pueden recibir notificaciones cuando cambia el tema del sistema controlando el evento Application.RequestedThemeChanged:

Application.Current.RequestedThemeChanged += (s, a) =>
{
    // Respond to the theme change
};

El objeto AppThemeChangedEventArgs que acompaña al evento RequestedThemeChanged tiene una única propiedad denominada RequestedTheme, de tipo OSAppTheme. Esta propiedad se puede examinar para detectar el tema del sistema solicitado.

Importante

Para responder a los cambios de tema en Android, debe incluir la marca ConfigChanges.UiMode en el atributo Activity de la clase MainActivity.