Прочитать на английском

Поделиться через


Тема приложения

Просмотрите пример. Обзор примера

Приложения пользовательского интерфейса мультиплатформенных приложений .NET (.NET MAUI) могут динамически реагировать на изменения стиля во время выполнения с помощью DynamicResource расширения разметки. Это расширение разметки аналогично StaticResource расширению разметки, в том, что оба используют ключ словаря для получения значения из ResourceDictionary. Однако в то время как StaticResource расширение разметки выполняет поиск одного словаря, DynamicResource расширение разметки сохраняет ссылку на ключ словаря. Поэтому, если значение, связанное с ключом, заменяется, то к нему VisualElementприменяется изменение. Это позволяет реализовать их во время выполнения в приложениях .NET MAUI.

Процесс реализации тем среды выполнения в приложении .NET MAUI выглядит следующим образом:

  1. Определите ресурсы для каждой темы в объекте ResourceDictionary. Дополнительные сведения см. в разделе "Определение тем".
  2. Задайте тему по умолчанию в файле App.xaml приложения. Дополнительные сведения см. в разделе "Настройка темы по умолчанию".
  3. Использование ресурсов темы в приложении с помощью расширения разметки DynamicResource . Дополнительные сведения см. в разделе "Использование ресурсов темы".
  4. Добавьте код для загрузки темы во время выполнения. Дополнительные сведения см. в разделе "Загрузка темы во время выполнения".

Важно!

Используйте расширение разметки, если приложению StaticResource не нужно динамически изменять темы во время выполнения. Если вы ожидаете переключение тем во время работы приложения, используйте DynamicResource расширение разметки, которое позволяет обновлять ресурсы во время выполнения.

На следующем снимка экрана показаны тематические страницы с приложением iOS с помощью светлой темы и приложения Android с темной темой:

Снимок экрана: главная страница тематических приложений.

Примечание

Для изменения темы во время выполнения требуется использование определений стилей XAML или C# и невозможно использовать CSS.

В .NET MAUI также есть возможность реагировать на изменения системной темы. Системная тема может измениться по различным причинам в зависимости от конфигурации устройства. Это включает в себя явно измененную пользователем системную тему, ее изменение в связи с временем дня и изменение из-за экологических факторов, таких как низкий свет. Дополнительные сведения см. в разделе "Ответ на изменения системной темы".

Определение тем

Тема определяется как коллекция объектов ресурсов, хранящихся в объекте ResourceDictionary.

В следующем примере показана светлая ResourceDictionary тема с именем LightTheme:

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

В следующем примере показана ResourceDictionary темная тема с именем DarkTheme:

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

Каждый ResourceDictionary содержит Color ресурсы, определяющие соответствующие темы, с каждым из которых ResourceDictionary используются одинаковые значения ключей. Дополнительные сведения о словарях ресурсов см. в разделах "Словари ресурсов".

Важно!

Для каждого ResourceDictionaryфайла, вызывающего метод, требуется код за файлом InitializeComponent . Это необходимо, чтобы объект CLR, представляющий выбранную тему, можно создать во время выполнения.

Настройка темы по умолчанию

Для приложения требуется тема по умолчанию, чтобы элементы управления имели значения для используемых ресурсов. Тему по умолчанию можно задать, объединив тему ResourceDictionary на уровень ResourceDictionary приложения, определенный в App.xaml:

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>

Дополнительные сведения о слиянии словарей ресурсов см . в объединенных словарях ресурсов.

Использование ресурсов темы

Если приложение хочет использовать ресурс, хранящийся в объекте ResourceDictionary , представляющего тему, он должен сделать это с расширением DynamicResource разметки. Это гарантирует, что при выборе другой темы во время выполнения будут применены значения из новой темы.

В следующем примере показаны три стиля, которые можно применить ко всем Label объектам в приложении:

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>

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

Эти стили определяются в словаре ресурсов на уровне приложения, чтобы их можно было использовать на нескольких страницах. Каждый стиль использует ресурсы темы с расширением разметки DynamicResource .

Затем эти стили используются страницами:

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

Если ресурс темы используется напрямую, его следует использовать с расширением DynamicResource разметки. Однако при использовании стиля, использующего DynamicResource расширение разметки, его следует использовать с расширением StaticResource разметки.

Дополнительные сведения о стилизации см. в разделе "Стили приложений с помощью XAML". Дополнительные сведения о расширении разметки см. в разделе "Динамические DynamicResource стили".

Загрузка темы во время выполнения

Если тема выбрана во время выполнения, приложение должно:

  1. Удалите текущую тему из приложения. Это достигается путем очистки MergedDictionaries свойства уровня ResourceDictionaryприложения.
  2. Загрузите выбранную тему. Это достигается путем добавления экземпляра выбранной темы в MergedDictionaries свойство уровня ResourceDictionaryприложения.

Затем все VisualElement объекты, которые задают свойства с расширением DynamicResource разметки, будут применять новые значения темы. Это происходит, так как DynamicResource расширение разметки поддерживает ссылку на ключи словаря. Поэтому при замене значений, связанных с ключами, изменения применяются к VisualElement объектам.

В примере приложения выбрана тема с помощью модальной страницы, содержащей объект Picker. В следующем коде показан OnPickerSelectionChanged метод, который выполняется при изменении выбранной темы:

В следующем примере показано удаление текущей темы и загрузка новой темы:

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