Xamarin.Forms アプリケーションでシステム テーマの変更に対応する
通常、デバイスにはライト テーマとダーク テーマが含まれ、それぞれがオペレーティング システム レベルで設定できる幅広い外観設定を指します。 アプリケーションでは、これらのシステム テーマを考慮し、システム テーマが変更されたときにすぐに対応する必要があります。
システム テーマは、デバイスの構成に応じてさまざまな理由で変更される場合があります。 これには、ユーザーによって明示的に変更されているシステム テーマ、時刻によって変更される、低光量などの環境要因によって変化するシステム テーマが含まれます。
Xamarin.Forms アプリケーションは、AppThemeBinding
マークアップ拡張および SetAppThemeColor
と SetOnAppTheme<T>
拡張メソッドでリソースを使って、システム テーマの変更に対応できます。
Xamarin.Forms でシステム テーマの変更に対応するには、次の要件が満たされている必要があります。
- Xamarin.Forms 4.6.0.967 以降。
- iOS 13 以降。
- Android 10 (API 29) 以降。
- UWP ビルド 14393 以降。
- macOS 10.14 以降。
次に示すのは、iOS と Android でライトとダークのシステム テーマが適用されたページのスクリーンショットです。
テーマ リソースの定義と使用
ライト テーマとダーク テーマのリソースは、AppThemeBinding
マークアップ拡張機能、SetAppThemeColor
拡張メソッドと SetOnAppTheme<T>
拡張メソッドと共に使用できます。 これらの方法では、現在のシステム テーマの値に基づいてリソースが自動的に適用されます。 さらに、これらのリソースを使用するオブジェクトは、アプリの実行中にシステム テーマが変更された場合に自動的に更新されます。
AppThemeBinding マークアップ拡張
AppThemeBinding
マークアップ拡張を使うと、現在のシステム テーマに基づいて、画像や色などのリソースを使用できます。
<ContentPage ...>
<StackLayout Margin="20">
<Label Text="This text is green in light mode, and red in dark mode."
TextColor="{AppThemeBinding Light=Green, Dark=Red}" />
<Image Source="{AppThemeBinding Light=lightlogo.png, Dark=darklogo.png}" />
</StackLayout>
</ContentPage>
この例では、デバイスがライト テーマを使用している場合、最初の Label
のテキストの色が緑色に設定され、デバイスがダーク テーマを使用している場合は赤色に設定されます。 同様に、Image
は現在のシステム テーマに基づいて異なるイメージ ファイルを表示します。
さらに、ResourceDictionary
で定義されたリソースは、StaticResource
マークアップ拡張機能を使用することもできます。
<ContentPage ...>
<ContentPage.Resources>
<!-- Light colors -->
<Color x:Key="LightPrimaryColor">WhiteSmoke</Color>
<Color x:Key="LightSecondaryColor">Black</Color>
<!-- Dark colors -->
<Color x:Key="DarkPrimaryColor">Teal</Color>
<Color x:Key="DarkSecondaryColor">White</Color>
<Style x:Key="ButtonStyle"
TargetType="Button">
<Setter Property="BackgroundColor"
Value="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}" />
<Setter Property="TextColor"
Value="{AppThemeBinding Light={StaticResource LightSecondaryColor}, Dark={StaticResource DarkSecondaryColor}}" />
</Style>
</ContentPage.Resources>
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}">
<Button Text="MORE INFO"
Style="{StaticResource ButtonStyle}" />
</Grid>
</ContentPage>
この例では、デバイスがライト テーマとダーク テーマのどちらを使用しているかに基づいて、Grid
と Button
スタイルの背景色が変わります。
AppThemeBinding
マークアップ拡張について詳しくは、「AppThemeBinding マークアップ拡張」をご覧ください。
拡張メソッド
Xamarin.Forms に含まれる SetAppThemeColor
および SetOnAppTheme<T>
拡張メソッドを使うと、VisualElement
オブジェクトでシステム テーマの変更に対応できます。
SetAppThemeColor
メソッドを使用すると、現在のシステム テーマに基づいてターゲット プロパティに設定される Color
オブジェクトを指定できます。
Label label = new Label();
label.SetAppThemeColor(Label.TextColorProperty, Color.Green, Color.Red);
この例では、デバイスがライト テーマを使用している場合、Label
のテキストの色は緑色に設定され、デバイスがダーク テーマを使用している場合は赤色に設定されます。
SetOnAppTheme<T>
メソッドを使用すると、現在のシステム テーマに基づいてターゲット プロパティに設定される T
型のオブジェクトを指定できます。
Image image = new Image();
image.SetOnAppTheme<FileImageSource>(Image.SourceProperty, "lightlogo.png", "darklogo.png");
この例では、Image
は、デバイスがライト テーマを使用しているときには lightlogo.png
を表示し、デバイスがダーク テーマを使用しているときには darklogo.png
を表示します。
現在のシステム テーマを検出する
現在のシステム テーマは、Application.RequestedTheme
プロパティの値を取得することで検出できます。
OSAppTheme currentTheme = Application.Current.RequestedTheme;
RequestedTheme
プロパティでは、OSAppTheme
と呼ばれる列挙型が返されます。 OSAppTheme
列挙型には、次のメンバーが定義されています。
Unspecified
は、デバイスが未指定のテーマを使用していることを示します。Light
は、デバイスがライト テーマを使用していることを示します。Dark
は、デバイスがダーク テーマを使用していることを示します。
現在のユーザー テーマを設定する
現在機能するシステム テーマに関係なく、アプリケーションで使われるテーマは、OSAppTheme
型の Application.UserAppTheme
プロパティで設定できます。
Application.Current.UserAppTheme = OSAppTheme.Dark;
この例では、現在機能するシステム テーマに関係なく、システム ダーク モード用に定義されているテーマを使うようにアプリケーションを設定しています。
Note
UserAppTheme
プロパティを OSAppTheme.Unspecified
に設定すると、既定でオペレーティング システム テーマに設定されます。
テーマの変更に対応する
デバイスのシステム テーマは、デバイスの構成に応じて、さまざまな理由で変更される場合があります。 Xamarin.Forms アプリでは、Application.RequestedThemeChanged
イベントを処理することで、システム テーマが変更されたときに通知を受け取ることができます。
Application.Current.RequestedThemeChanged += (s, a) =>
{
// Respond to the theme change
};
RequestedThemeChanged
イベントに付随する AppThemeChangedEventArgs
オブジェクトには、OSAppTheme
型の RequestedTheme
という名前の単一プロパティがあります。 このプロパティを調べて、要求されたシステム テーマを検出できます。
重要
Android でテーマの変更に対応するには、MainActivity
クラスの Activity
属性に ConfigChanges.UiMode
フラグを含める必要があります。