Partilhar via


Tema de um Xamarin.Forms aplicativo

Xamarin.Forms Os aplicativos podem responder a alterações de estilo dinamicamente em runtime usando a extensão de DynamicResource marcação. A extensão de marcação é semelhante à extensão de marcação StaticResource, pois ambas usam uma chave de dicionário para buscar um valor em um ResourceDictionary. No entanto, enquanto a extensão de marcação StaticResource executa uma única pesquisa de dicionário, a extensão de marcação DynamicResource mantém um link para a 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 Xamarin.Forms aplicativos.

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

  1. Definir os recursos para cada tema em um ResourceDictionary.
  2. Consuma recursos de tema no aplicativo, usando a extensão de DynamicResource marcação.
  3. Defina um tema padrão no arquivo App.xaml do aplicativo.
  4. Adicionar código para carregar um tema em runtime.

Importante

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

As capturas de tela a seguir mostram páginas temáticas, com o aplicativo iOS usando um tema claro e o aplicativo Android usando um tema escuro:

Captura de tela da página principal de um aplicativo temático, no iOS e AndroidCaptura de tela da página de detalhes de um aplicativo temático, no iOS e Android

Observação

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

Definir temas

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

O exemplo a seguir mostra o LightTheme aplicativo de exemplo:

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    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 o DarkTheme aplicativo de exemplo:

<ResourceDictionary xmlns="http://xamarin.com/schemas/2014/forms"
                    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 ResourceDictionary um contém recursos Color que definem seus respectivos temas, com cada ResourceDictionary usando valores de chave idênticos. Para mais informações sobre dicionários de recursos, confira Dicionários de recursos.

Importante

É necessário um arquivo code-behind para cada ResourceDictionary, que chama o método InitializeComponent. Isso é necessário para que um objeto CLR que representa o tema escolhido possa ser criado em runtime.

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 no nível ResourceDictionary do ResourceDictionary aplicativo definido em App.xaml:

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

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

Consumir recursos de tema

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

O exemplo a seguir mostra três estilos do aplicativo de exemplo que podem ser aplicados a Label objetos:

<Application xmlns="http://xamarin.com/schemas/2014/forms"
             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 extensão de marcação DynamicResource.

Esses estilos são então consumidos por páginas:

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             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 extensão de marcação DynamicResource. No entanto, quando um estilo que usa a extensão de marcação DynamicResource é consumido, ele deve ser consumido com a extensão de marcação StaticResource.

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

Carregar um tema em runtime

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

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

Todos os objetos VisualElement que definem propriedades com a extensão de marcação DynamicResource aplicarão os novos valores de tema. Isso ocorre porque a extensão de marcação DynamicResource 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 objetos VisualElement.

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

void OnPickerSelectionChanged(object sender, EventArgs e)
{
    Picker picker = sender as Picker;
    Theme theme = (Theme)picker.SelectedItem;

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

        switch (theme)
        {
            case Theme.Dark:
                mergedDictionaries.Add(new DarkTheme());
                break;
            case Theme.Light:
            default:
                mergedDictionaries.Add(new LightTheme());
                break;
        }
    }
}