アプリのテーマを設定

Browse sample. サンプルを参照する

.NET マルチプラットフォーム アプリ UI (.NET MAUI) アプリは、DynamicResource マークアップ拡張を使用して、実行時にスタイルの変更に動的に応答できます。 このマークアップ拡張は StaticResource マークアップ拡張に似ていますが、どちらも辞書キーを使用して ResourceDictionary から値を取り込みます。 ただし、StaticResource マークアップ拡張は単一の辞書検索を実行しますが、DynamicResource マークアップ拡張は、辞書キーへのリンクを維持します。 そのため、キーに関連付けられている値が置き換えられると、その変更は VisualElement に適用されます。 これにより、ランタイム テーマを .NET MAUI アプリに実装できます。

.NET MAUI アプリでランタイム テーマを実装するプロセスは、次のとおりです。

  1. ResourceDictionary で各テーマのリソースを定義します。 詳細については、「テーマの定義」をご覧ください。
  2. アプリの "アプリ.xaml" ファイルにデフォルトのテーマを設定します。 詳細については、「デフォルトのテーマを設定」をご覧ください。
  3. DynamicResource マークアップ拡張を使用して、アプリでテーマ リソースを使用します。 詳細については、「テーマ リソースの使用」をご覧ください。
  4. 実行時にテーマを読み込むコードを追加します。 詳細については、「実行時にテーマを読み込む」をご覧ください。

重要

実行時にアプリ テーマを変更する必要がない場合は、StaticResource マークアップ拡張を使用します。

次のスクリーンショットは、テーマ付きページを示しています。iOS アプリではライト テーマを使用し、Android アプリはダーク テーマを使用しています。

Screenshot of the main page of a themed app.

Note

実行時にテーマを変更するには、XAML スタイルを使用する必要があります。CSS を使用することはできません。

.NET MAUI には、システム テーマの変更に対応する機能もあります。 システム テーマは、デバイスの構成に応じてさまざまな理由で変更される場合があります。 これには、システムテーマがユーザーによって明示的に変更されること、時間帯によって変更されること、低照度などの環境要因によって変更されることが含まれます。 詳細については、「システム テーマの変更に対応する」をご覧ください。

テーマの定義

テーマは、ResourceDictionary に格納されているリソース オブジェクトのコレクションとして定義されます。

次の例は、LightTheme という名前のライト テーマの ResourceDictionary を示しています。

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

次の例は、DarkTheme という名前のダーク テーマの ResourceDictionary を示しています。

<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 を、"アプリ.xaml" で定義されているアプリレベルの ResourceDictionary にマージすることで設定できます。

<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 オブジェクトに適用できる、3 つのスタイルを示しています。

<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 マークアップ拡張を持つテーマ リソースを使用します。

その後、これらのスタイルをページで使用します。

<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. アプリから現在のテーマを削除します 。 これは、アプリ レベル ResourceDictionaryMergedDictionaries プロパティをクリアすることによって実現されます。
  2. 選択したテーマを読み込みます。 これは、選択したテーマのインスタンスをアプリ レベル ResourceDictionaryMergedDictionaries プロパティに追加することによって実現されます。

DynamicResource マークアップ拡張機能を使用してプロパティを設定する VisualElement オブジェクトは、新しいテーマの値を適用します。 これは、DynamicResource マークアップ拡張機能に辞書キーへのリンクが含まれているために発生します。 したがって、キーに関連付けられている値が置き換えられると、変更が VisualElement オブジェクトに適用されます。

サンプル アプリケーションでは、テーマは Picker が含まれているモーダル ページを使用して選択されます。 次のコードは、選択したテーマが変更されたときに実行される OnPickerSelectionChanged メソッドを示しています。

次の例は、現在のテーマを削除し、新しいテーマを読み込む方法を示しています。

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