Responder a alterações de tema do sistema

Procurar exemplo. Procurar o exemplo

Os dispositivos normalmente incluem temas claros e escuros, cada um referindo-se a um conjunto amplo de preferências de aparência que podem ser definidas ao nível do sistema operativo. As aplicações devem respeitar estes temas do sistema e responder imediatamente quando o tema do sistema mudar.

O tema do sistema pode mudar por várias razões, dependendo da configuração do dispositivo. Isto inclui o tema do sistema ser explicitamente alterado pelo utilizador, alterado devido à hora do dia e alterado devido a fatores ambientais como pouca luz.

As aplicações .NET Multi-platform App UI (.NET MAUI) podem responder a alterações de temas do sistema consumindo recursos com a extensão de marcação AppThemeBinding e os métodos de extensão SetAppThemeColor e SetAppTheme<T>.

Observação

As aplicações .NET MAUI podem responder a alterações de temas de sistema no iOS 13 ou superior, Android 10 (API 29) ou superior, macOS 10.14 ou superior, e Windows 10 ou superior.

A captura de ecrã seguinte mostra páginas temáticas, para o tema do sistema claro no iOS e o tema do sistema escuro no Android:

Captura de ecrã da página principal de uma aplicação temática.

Defina e consuma recursos temáticos

Recursos para temas claros e escuros podem ser consumidos com a extensão de marcação AppThemeBinding, bem como com os métodos de extensão SetAppThemeColor e SetAppTheme<T>. Com estas abordagens, os recursos são automaticamente aplicados com base no valor do tema atual do sistema. Além disso, os objetos que consomem estes recursos são automaticamente atualizados se o tema do sistema mudar enquanto a aplicação está a correr.

Extensão de marcação do AppThemeBinding

A AppThemeBinding extensão de marcação permite-lhe consumir um recurso, como uma imagem ou cor, com base no tema atual do sistema.

A AppThemeBinding extensão de marcação é suportada pela AppThemeBindingExtension classe, que define as seguintes propriedades:

  • Default, do tipo object, que defines para o recurso a ser usado como padrão.
  • Light, do tipo object, que defines para o recurso a ser usado quando o dispositivo está a usar o seu tema de luz.
  • Dark, do tipo object, que defines para o recurso a ser usado quando o dispositivo está a usar o seu tema escuro.
  • Value, do tipo object, que devolve o recurso que está a ser utilizado atualmente pela extensão de marcação.

Observação

O analisador XAML permite que a classe AppThemeBindingExtension seja abreviada como AppThemeBinding.

A Default propriedade é a propriedade de conteúdo de AppThemeBindingExtension. Portanto, para expressões de marcação XAML expressas com colchetes, pode-se eliminar a Default= parte da expressão desde que seja o primeiro argumento.

O seguinte exemplo de XAML mostra como usar a AppThemeBinding extensão de marcação:

<StackLayout>
    <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>

Neste exemplo, a cor do texto do primeiro Label é definida para verde quando o dispositivo usa o seu tema claro, e é definida para vermelho quando o dispositivo usa o seu tema escuro. De forma semelhante, Image apresenta um ficheiro de imagem diferente com base no tema atual do sistema.

Recursos definidos num ResourceDictionary podem ser consumidos em AppThemeBinding com a StaticResource extensão de marcação:

<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>    

Neste exemplo, a cor de fundo do Grid e o Button estilo muda consoante se o dispositivo está a usar o tema claro ou o tema escuro.

Além disso, recursos definidos em um ResourceDictionary também podem ser consumidos em um AppThemeBinding com a DynamicResource extensão de marcação.

<ContentPage ...>
    <ContentPage.Resources>
        <Color x:Key="Primary">DarkGray</Color>
        <Color x:Key="Secondary">HotPink</Color>
        <Color x:Key="Tertiary">Yellow</Color>
        <Style x:Key="labelStyle" TargetType="Label">
            <Setter Property="Padding" Value="5"/>
            <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Primary}}" />
            <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={DynamicResource Primary}, Dark={DynamicResource Secondary}}" />
        </Style>
    </ContentPage.Resources>
    <Label x:Name="myLabel"
           Style="{StaticResource labelStyle}"/>
</ContentPage>

Métodos de extensão

O .NET MAUI inclui métodos de extensão, SetAppThemeColor e SetAppTheme<T>, que permitem que objetos VisualElement respondam a alterações de temas do sistema.

O SetAppThemeColor método permite Color especificar objetos que serão definidos numa propriedade alvo baseada no tema atual do sistema:

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

Neste exemplo, a cor do Label texto é definida para verde quando o dispositivo usa o seu tema claro, e está definida para vermelho quando o dispositivo usa o seu tema escuro.

O SetAppTheme<T> método permite especificar objetos do tipo T que serão definidos numa propriedade alvo baseada no tema atual do sistema:

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

Neste exemplo, exibe Imagelightlogo.png quando o dispositivo está a usar o seu tema claro e darklogo.png quando o dispositivo está a usar o seu tema escuro.

Detetar o tema atual do sistema

O tema atual do sistema pode ser detetado obtendo o valor da Application.RequestedTheme propriedade:

AppTheme currentTheme = Application.Current.RequestedTheme;

A RequestedTheme propriedade devolve um AppTheme membro de enumeração. A enumeração AppTheme define os seguintes membros:

  • Unspecified, o que indica que o dispositivo está a usar um tema não especificado.
  • Light, o que indica que o dispositivo está a usar o seu tema de luz.
  • Dark, o que indica que o dispositivo está a usar o seu tema escuro.

Definir o tema do utilizador atual

O tema usado pela aplicação pode ser definido com a Application.UserAppTheme propriedade, que é do tipo AppTheme, independentemente do tema do sistema que esteja atualmente em operação:

Application.Current.UserAppTheme = AppTheme.Dark;

Neste exemplo, a aplicação está definida para usar o tema definido para o modo escuro do sistema, independentemente do tema do sistema atualmente operacional.

Observação

Defina a UserAppTheme propriedade para AppTheme.Unspecified o tema do sistema operacional por defeito.

Reagir às mudanças de tema

O tema do sistema num dispositivo pode mudar por várias razões, dependendo de como o dispositivo está configurado. As aplicações .NET MAUI podem ser notificadas sobre a mudança de tema do sistema ao lidar com o evento Application.RequestedThemeChanged.

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

O AppThemeChangedEventArgs objeto, que acompanha o RequestedThemeChanged evento, tem uma única propriedade chamada RequestedTheme, de tipo AppTheme. Esta propriedade pode ser examinada para detetar o tema do sistema solicitado.

Importante

Para responder a alterações de tema no Android, a sua MainActivity classe deve incluir a ConfigChanges.UiMode flag no Activity atributo. As aplicações .NET MAUI criadas com os templates do projeto Visual Studio incluem automaticamente esta bandeira.