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

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

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

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

.NETマルチプラットフォーム アプリUI(.NET MAUI)アプリは、AppThemeBinding マークアップ拡張、および SetAppThemeColor 拡張メソッドと SetAppTheme<T> 拡張メソッドでリソースを消費することで、システムテーマの変更に対応できます。

Note

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

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

Screenshot of the main page of a themed app.

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

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

AppThemeBinding マークアップ拡張

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

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

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

Note

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

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");

この例では、デバイスが明るいテーマを使用している場合は Imagelightlogo.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 アプリには、このフラグが自動的に含まれます。