Tema de um aplicativo

Browse sample. Navegue pelo exemplo

Os aplicativos .NET Multi-platform App UI (.NET MAUI) podem responder a alterações de estilo dinamicamente em tempo de execução usando a extensão de DynamicResource marcação. Essa extensão de marcação é semelhante à StaticResource extensão de marcação, em que ambos usam uma chave de dicionário para buscar um valor de um ResourceDictionaryarquivo . No entanto, enquanto a extensão de marcação executa uma única pesquisa de dicionário, a extensão de marcação mantém um link para a StaticResourceDynamicResource chave de dicionário. Portanto, se o valor associado à chave for substituído, a alteração será aplicada ao VisualElement. Isso permite que o tema de tempo de execução seja implementado em aplicativos .NET MAUI.

O processo para implementar temas de tempo de execução em um aplicativo .NET MAUI é o seguinte:

  1. Defina os recursos para cada tema em um ResourceDictionaryarquivo . Para obter mais informações, consulte Definir temas.
  2. Defina um tema padrão no arquivo App.xaml do aplicativo. Para obter mais informações, consulte Definir um tema padrão.
  3. Consuma recursos de tema no aplicativo, usando a DynamicResource extensão de marcação. Para obter mais informações, consulte Consumir recursos de tema.
  4. Adicione código para carregar um tema em tempo de execução. Para obter mais informações, consulte Carregar um tema em tempo de execução.

Importante

Use a StaticResource extensão de marcação se não precisar alterar o tema do aplicativo em tempo de execução.

A captura de tela a seguir mostra páginas temáticas, com o aplicativo iOS usando um tema claro e o aplicativo Android usando um tema escuro:

Screenshot of the main page of a themed app.

Observação

A alteração de um tema em tempo de execução requer o uso de estilos XAML e não é possível usando CSS.

O .NET MAUI também tem a capacidade de responder a alterações de tema do sistema. O tema do sistema pode mudar por vários motivos, dependendo da configuração do dispositivo. Isso inclui o tema do sistema sendo explicitamente alterado pelo usuário, ele mudando devido à hora do dia, e ele mudando devido a fatores ambientais, como pouca luz. Para obter mais informações, consulte Responder a alterações de tema do sistema.

Definir temas

Um tema é definido como uma coleção de objetos de recurso armazenados em um ResourceDictionaryarquivo .

O exemplo a seguir mostra um para um ResourceDictionary tema leve chamado LightTheme:

<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="ThemingDemo.LightTheme">
    <Color x:Key="PageBackgroundColor">White</Color>
    <Color x:Key="NavigationBarColor">WhiteSmoke</Color>
    <Color x:Key="PrimaryColor">WhiteSmoke</Color>
    <Color x:Key="SecondaryColor">Black</Color>
    <Color x:Key="PrimaryTextColor">Black</Color>
    <Color x:Key="SecondaryTextColor">White</Color>
    <Color x:Key="TertiaryTextColor">Gray</Color>
    <Color x:Key="TransparentColor">Transparent</Color>
</ResourceDictionary>

O exemplo a seguir mostra um para um ResourceDictionary tema escuro chamado DarkTheme:

<ResourceDictionary xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
                    xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
                    x:Class="ThemingDemo.DarkTheme">
    <Color x:Key="PageBackgroundColor">Black</Color>
    <Color x:Key="NavigationBarColor">Teal</Color>
    <Color x:Key="PrimaryColor">Teal</Color>
    <Color x:Key="SecondaryColor">White</Color>
    <Color x:Key="PrimaryTextColor">White</Color>
    <Color x:Key="SecondaryTextColor">White</Color>
    <Color x:Key="TertiaryTextColor">WhiteSmoke</Color>
    <Color x:Key="TransparentColor">Transparent</Color>
</ResourceDictionary>

Cada um ResourceDictionary contém Color recursos que definem seus respectivos temas, com cada um ResourceDictionary usando valores de chave idênticos. Para obter mais informações sobre dicionários de recursos, consulte Dicionários de recursos.

Importante

Um arquivo code-behind é necessário para cada ResourceDictionary, que chama o InitializeComponent método. Isso é necessário para que um objeto CLR que represente o tema escolhido possa ser criado em tempo de execução.

Definir um tema padrão

Um aplicativo requer um tema padrão, para que os controles tenham valores para os recursos que consomem. Um tema padrão pode ser definido mesclando o tema ResourceDictionary no nível ResourceDictionary do aplicativo definido em App.xaml:

<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ThemingDemo.App">
    <Application.Resources>
        <ResourceDictionary Source="Themes/LightTheme.xaml" />
    </Application.Resources>
</Application>

Para obter mais informações sobre como mesclar dicionários de recursos, consulte Dicionários de recursos mesclados.

Consumir recursos de tema

Quando um aplicativo deseja consumir um recurso armazenado em um que representa um ResourceDictionary tema, ele deve fazê-lo com a DynamicResource extensão de marcação. Isso garante que, se um tema diferente for selecionado em tempo de execução, os valores do novo tema serão aplicados.

O exemplo a seguir mostra três estilos que podem ser aplicados a todos os Label objetos no aplicativo:

<Application xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="ThemingDemo.App">
    <Application.Resources>

        <Style x:Key="LargeLabelStyle"
               TargetType="Label">
            <Setter Property="TextColor"
                    Value="{DynamicResource SecondaryTextColor}" />
            <Setter Property="FontSize"
                    Value="30" />
        </Style>

        <Style x:Key="MediumLabelStyle"
               TargetType="Label">
            <Setter Property="TextColor"
                    Value="{DynamicResource PrimaryTextColor}" />
            <Setter Property="FontSize"
                    Value="25" />
        </Style>

        <Style x:Key="SmallLabelStyle"
               TargetType="Label">
            <Setter Property="TextColor"
                    Value="{DynamicResource TertiaryTextColor}" />
            <Setter Property="FontSize"
                    Value="15" />
        </Style>

    </Application.Resources>
</Application>

Esses estilos são definidos no dicionário de recursos no nível do aplicativo, para que possam ser consumidos por várias páginas. Cada estilo consome recursos de tema com a DynamicResource extensão de marcação.

Esses estilos são consumidos pelas páginas:

<ContentPage xmlns="http://schemas.microsoft.com/dotnet/2021/maui"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             xmlns:local="clr-namespace:ThemingDemo"
             x:Class="ThemingDemo.UserSummaryPage"
             Title="User Summary"
             BackgroundColor="{DynamicResource PageBackgroundColor}">
    ...
    <ScrollView>
        <Grid>
            <Grid.RowDefinitions>
                <RowDefinition Height="200" />
                <RowDefinition Height="120" />
                <RowDefinition Height="70" />
            </Grid.RowDefinitions>
            <Grid BackgroundColor="{DynamicResource PrimaryColor}">
                <Label Text="Face-Palm Monkey"
                       VerticalOptions="Center"
                       Margin="15"
                       Style="{StaticResource MediumLabelStyle}" />
                ...
            </Grid>
            <StackLayout Grid.Row="1"
                         Margin="10">
                <Label Text="This monkey reacts appropriately to ridiculous assertions and actions."
                       Style="{StaticResource SmallLabelStyle}" />
                <Label Text="  &#x2022; Cynical but not unfriendly."
                       Style="{StaticResource SmallLabelStyle}" />
                <Label Text="  &#x2022; Seven varieties of grimaces."
                       Style="{StaticResource SmallLabelStyle}" />
                <Label Text="  &#x2022; Doesn't laugh at your jokes."
                       Style="{StaticResource SmallLabelStyle}" />
            </StackLayout>
            ...
        </Grid>
    </ScrollView>
</ContentPage>

Quando um recurso de tema é consumido diretamente, ele deve ser consumido com a DynamicResource extensão de marcação. No entanto, quando um estilo que usa a extensão de marcação é consumido, ele deve ser consumido com a StaticResource extensão de DynamicResource marcação.

Para obter mais informações sobre estilo, consulte Estilizar aplicativos usando XAML. Para obter mais informações sobre a extensão de DynamicResource marcação, consulte Estilos dinâmicos.

Carregar um tema em tempo de execução

Quando um tema é selecionado em tempo de execução, um aplicativo deve:

  1. Remova o tema atual do aplicativo. Isso é feito limpando a MergedDictionaries propriedade do nível ResourceDictionarydo aplicativo.
  2. Carregue o tema selecionado. Isso é obtido adicionando uma instância do tema selecionado à MergedDictionaries propriedade do nível ResourceDictionarydo aplicativo.

Todos os objetos que definem propriedades com a extensão de DynamicResource marcação aplicarão os VisualElement novos valores de tema. Isso ocorre porque a extensão de DynamicResource marcação mantém um link para chaves de dicionário. Portanto, quando os valores associados às chaves são substituídos, as alterações são aplicadas aos VisualElement objetos.

No aplicativo de exemplo, um tema é selecionado por meio de uma página modal que contém um Pickerarquivo . O código a seguir mostra o método, que é executado quando o OnPickerSelectionChanged tema selecionado é alterado:

O exemplo a seguir mostra a remoção do tema atual e o carregamento de um novo tema:

ICollection<ResourceDictionary> mergedDictionaries = Application.Current.Resources.MergedDictionaries;
if (mergedDictionaries != null)
{
    mergedDictionaries.Clear();
    mergedDictionaries.Add(new DarkTheme());
}