システム テーマの変更に対応する

サンプルを参照します。 サンプルを参照する

通常、デバイスにはライト テーマとダーク テーマが含まれ、それぞれがオペレーティング システム レベルで設定できる幅広い外観設定を指します。 アプリはこれらのシステム テーマを尊重し、システム テーマが変更されたときにすぐに対応する必要があります。

システム テーマは、デバイスの構成に応じてさまざまな理由で変更される場合があります。 これには、ユーザーによって明示的に変更されているシステム テーマ、時刻によって変更される、低光量などの環境要因によって変化するシステム テーマが含まれます。

.NET Multi-platform App UI (.NET MAUI) アプリは、AppThemeBinding マークアップ拡張機能や SetAppThemeColor 拡張メソッドと SetAppTheme<T> 拡張メソッドを使用してリソースを使用することで、システム テーマの変更に対応できます。

Note

.NET MAUI アプリは、iOS 13 以上、Android 10 (API 29) 以降、macOS 10.14 以降、Windows 10 以降でのシステム テーマの変更に対応できます。

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

テーマが適用されたアプリのメイン ページのスクリーンショット。

テーマ リソースの定義と使用

ライト テーマとダーク テーマのリソースは、AppThemeBinding マークアップ拡張機能、SetAppThemeColor 拡張メソッドと SetAppTheme<T> 拡張メソッドと共に使用できます。 これらの方法では、現在のシステム テーマの値に基づいてリソースが自動的に適用されます。 さらに、これらのリソースを使用するオブジェクトは、アプリの実行中にシステム テーマが変更された場合に自動的に更新されます。

AppThemeBinding マークアップ拡張

AppThemeBinding マークアップ拡張機能を使用すると、現在のシステム テーマに基づいて、イメージや色などのリソースを使用できます。

AppThemeBinding マークアップ拡張機能は、次のプロパティを定義する AppThemeBindingExtension クラスによってサポートされています。

  • object 型の Default は、既定で使用するリソースに設定します。
  • object 型の Light は、デバイスがライト テーマを使用しているときに使用するリソースに設定します。
  • object 型の Dark は、デバイスがダーク テーマを使用しているときに使用するリソースに設定します。
  • object 型の Value は、マークアップ拡張機能によって現在使用されているリソースを返します。

Note

XAML パーサーでは、AppThemeBindingExtension クラスを AppThemeBinding に短縮できます。

Default プロパティは、AppThemeBindingExtension のコンテンツ プロパティです。 したがって、中かっこで表現された XAML マークアップ拡張機能の場合、それが最初の引数であれば、式の Default= 部分を削除できます。

次の XAML の例では、AppThemeBinding マークアップ拡張機能を使用する方法が示されています。

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

この例では、デバイスがライト テーマを使用している場合、最初の Label のテキストの色が緑色に設定され、デバイスがダーク テーマを使用している場合は赤色に設定されます。 同様に、Image は現在のシステム テーマに基づいて異なるイメージ ファイルを表示します。

ResourceDictionary で定義されているリソースは、StaticResource マークアップ拡張機能を使用して AppThemeBinding で使用できます。

<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 スタイルの背景色が変わります。

さらに、ResourceDictionary で定義されているリソースは、DynamicResource マークアップ拡張機能を使用して AppThemeBinding で使用することもできます。

<ContentPage ...>
    <ContentPage.Resources>
        <Color x:Key="Primary">DarkGray</Color>
        <Color x:Key="Secondary">HotPink</Color>
        <Color x:Key="Tertiary">Yellow</Color>
        <Style x:Key="labelStyle" TargetType="Label">
            <Setter Property="Padding" Value="5"/>
            <Setter Property="TextColor" Value="{AppThemeBinding Light={StaticResource Secondary}, Dark={StaticResource Primary}}" />
            <Setter Property="BackgroundColor" Value="{AppThemeBinding Light={DynamicResource Primary}, Dark={DynamicResource Secondary}}" />
        </Style>
    </ContentPage.Resources>
    <Label x:Name="myLabel"
           Style="{StaticResource labelStyle}"/>
</ContentPage>

拡張メソッド

.NET MAUI には、VisualElement オブジェクトがシステム テーマの変更に対応できるようにする SetAppThemeColor 拡張メソッドと SetAppTheme<T> 拡張メソッドが含まれています。

SetAppThemeColor メソッドを使用すると、現在のシステム テーマに基づいてターゲット プロパティに設定される Color オブジェクトを指定できます。

Label label = new Label();
label.SetAppThemeColor(Label.TextColorProperty, Colors.Green, Colors.Red);

この例では、デバイスがライト テーマを使用している場合、Label のテキストの色は緑色に設定され、デバイスがダーク テーマを使用している場合は赤色に設定されます。

SetAppTheme<T> メソッドを使用すると、現在のシステム テーマに基づいてターゲット プロパティに設定される T 型のオブジェクトを指定できます。

Image image = new Image();
image.SetAppTheme<FileImageSource>(Image.SourceProperty, "lightlogo.png", "darklogo.png");

この例では、Image は、デバイスがライト テーマを使用しているときには lightlogo.png を表示し、デバイスがダーク テーマを使用しているときには darklogo.png を表示します。

現在のシステム テーマを検出する

現在のシステム テーマは、Application.RequestedTheme プロパティの値を取得することで検出できます。

AppTheme currentTheme = Application.Current.RequestedTheme;

RequestedTheme プロパティでは、AppTheme と呼ばれる列挙型が返されます。 AppTheme 列挙型には、次のメンバーが定義されています。

  • Unspecified は、デバイスが未指定のテーマを使用していることを示します。
  • Light は、デバイスがライト テーマを使用していることを示します。
  • Dark は、デバイスがダーク テーマを使用していることを示します。

現在のユーザー テーマを設定する

アプリで使用されるテーマは、現在動作しているシステム テーマに関係なく、AppTheme 型の Application.UserAppTheme プロパティで設定できます。

Application.Current.UserAppTheme = AppTheme.Dark;

この例では、現在動作しているシステム テーマに関係なく、システム ダーク モード用に定義されたテーマを使用するようにアプリが設定されています。

Note

UserAppTheme プロパティを AppTheme.Unspecified に設定すると、既定でオペレーティング システム テーマに設定されます。

テーマの変更に対応する

デバイスのシステム テーマは、デバイスの構成に応じて、さまざまな理由で変更される場合があります。 .NET MAUI アプリは、Application.RequestedThemeChanged イベントを処理することで、システム テーマが変更されたときに通知を受け取ることができます。

Application.Current.RequestedThemeChanged += (s, a) =>
{
    // Respond to the theme change
};

RequestedThemeChanged イベントに付随する AppThemeChangedEventArgs オブジェクトには、AppTheme 型の RequestedTheme という名前の単一プロパティがあります。 このプロパティを調べて、要求されたシステム テーマを検出できます。

重要

Android でテーマの変更に対応するには、MainActivity クラスの Activity 属性に ConfigChanges.UiMode フラグが含まれている必要があります。 Visual Studio プロジェクト テンプレートで作成された .NET MAUI アプリには、このフラグが自動的に含まれています。