アプリにテーマを設定する
.NET Multi-Platform App UI (.NET MAUI) アプリでは、DynamicResource
マークアップ拡張を使用して、実行時にスタイルの変更に動的に応答できます。 このマークアップ拡張は、どちらもディクショナリ キーを使用して ResourceDictionary から値を取得するという点で、StaticResource
マークアップ拡張と似ています。 ただし、StaticResource
マークアップ拡張がディクショナリ検索を 1 回だけ実行するのに対して、DynamicResource
マークアップ拡張はディクショナリ キーへのリンクを保持します。 したがって、キーに関連付けられている値が置き換わると、その変更が VisualElement に適用されます。 これにより、ランタイムテーマを .NET MAUI アプリに実装できます。
.NET MAUI アプリにランタイムテーマを実装する手順は次のとおりです。
- 各テーマのリソースを ResourceDictionary に定義します。 詳細については、「テーマを定義する」をご覧ください。
- アプリの App.xaml ファイルに既定のテーマを設定します。 詳細については、「既定のテーマを設定する」をご覧ください。
DynamicResource
マークアップ拡張を使用して、アプリでテーマ リソースを使用します。 詳細については、「テーマ リソースを使用する」をご覧ください。- 実行時にテーマを読み込むコードを追加します。 詳細については、「実行時にテーマを読み込む」をご覧ください。
重要
アプリが実行時にテーマを動的に変更する必要がない場合は、StaticResource
マークアップ拡張を使用します。 アプリの実行中にテーマを切り替える予定がある場合は、DynamicResource
マークアップ拡張を使用します。これにより、実行時にリソースを更新できます。
次のスクリーンショットは、テーマ設定済みのページを示しています。iOS アプリではライト テーマを使用し、Android アプリではダーク テーマを使用しています。
Note
実行時にテーマを変更するには、XAML または C# スタイル定義を使用する必要があり、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 には、それぞれの ResourceDictionary で同一のキー値を使用して、それぞれのテーマを定義する Color リソースが含まれています。 リソース ディクショナリの詳細については、「リソース ディクショナリ」をご覧ください。
重要
InitializeComponent
メソッドを呼び出す分離コード ファイルが ResourceDictionary ごとに必要です。 これは、選択されたテーマを表す CLR オブジェクトを実行時に作成できるようにするために必要です。
既定のテーマを設定する
コントロールが使用するリソースの値を設定できるように、アプリには既定のテーマが必要です。 既定のテーマを設定するには、App.xaml で定義されているアプリ レベルの ResourceDictionary にテーマの 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=" • Cynical but not unfriendly."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Seven varieties of grimaces."
Style="{StaticResource SmallLabelStyle}" />
<Label Text=" • Doesn't laugh at your jokes."
Style="{StaticResource SmallLabelStyle}" />
</StackLayout>
...
</Grid>
</ScrollView>
</ContentPage>
テーマ リソースを直接使用する場合は、DynamicResource
マークアップ拡張で使用する必要があります。 ただし、DynamicResource
マークアップ拡張を使用するスタイルを使用する場合は、StaticResource
マークアップ拡張で使用する必要があります。
スタイル設定の詳細については、「XAML を使用したアプリのスタイル設定」をご覧ください。 DynamicResource
マークアップ拡張の詳細については、「動的スタイル」をご覧ください。
実行時にテーマを読み込む
実行時にテーマが選択されると、アプリは次の手順を実行する必要があります。
- アプリから現在のテーマを削除します。 それには、アプリ レベル ResourceDictionary の
MergedDictionaries
プロパティをクリアします。 - 選択したテーマを読み込みます。 それには、選択したテーマのインスタンスをアプリ レベルの ResourceDictionary の
MergedDictionaries
プロパティに追加します。
その結果、DynamicResource
マークアップ拡張を使用してプロパティを設定するすべての VisualElement オブジェクトが、新しいテーマの値を適用します。 このようになるのは、DynamicResource
マークアップ拡張がディクショナリ キーへのリンクを保持しているからです。 したがって、キーに関連付けられている値が置き換わると、その変更が VisualElement オブジェクトに適用されます。
サンプル アプリケーションでは、Picker を含んだモーダル ページを使用してテーマが選択されています。 次のコードは、選択したテーマが変更されたときに実行される OnPickerSelectionChanged
メソッドを示しています。
次の例は、現在のテーマを削除し新しいテーマを読み込む方法を示しています。
ICollection<ResourceDictionary> mergedDictionaries = Application.Current.Resources.MergedDictionaries;
if (mergedDictionaries != null)
{
mergedDictionaries.Clear();
mergedDictionaries.Add(new DarkTheme());
}
.NET MAUI