响应 Xamarin.Forms 应用程序中的系统主题更改

设备通常包含浅色主题和深色主题,每个主题都是指可以在操作系统级别设置的一组广泛的外观首选项。 应用程序应该遵循这些系统主题,并在系统主题发生更改时立即做出响应。

系统主题可能会因各种原因而更改,具体因设备配置而定。 这包括用户以显式方式更改系统主题,基于一天中的时间而更改,以及根据环境因素(如低亮度)而更改。

Xamarin.Forms 应用程序可以通过使用 AppThemeBinding 标记扩展以及 SetAppThemeColorSetOnAppTheme<T> 扩展方法使用资源来响应系统主题更改。

必须满足 Xamarin.Forms 的以下要求才能响应系统主题更改:

  • Xamarin.Forms 4.6.0.967 或更高版本。
  • iOS 13 或更高版本。
  • Android 10 (API 29) 或更高版本。
  • UWP 内部版本 14393 或更高版本。
  • macOS 10.14 或更高版本。

以下屏幕截图显示了 iOS 和 Android 上的浅色和深色系统主题的主题页:

iOS 和 Android 上主题应用的主页的屏幕截图iOS 和 Android 上主题应用的详细信息页面的屏幕截图

定义和使用主题资源

可以使用 AppThemeBinding 标记扩展以及 SetAppThemeColorSetOnAppTheme<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 可根据当前系统主题显示不同的图像文件。

此外,可以通过 StaticResource 标记扩展使用 ResourceDictionary 中定义的资源:

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

在此示例中,GridButton 样式的背景颜色会根据设备使用的是浅色主题还是深色主题而改变。

有关 AppThemeBinding 标记扩展的详细信息,请参阅 AppThemeBinding 标记扩展

扩展方法

Xamarin.Forms 包括 SetAppThemeColorSetOnAppTheme<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 指示设备正在使用其深色主题。

设置当前用户主题

应用程序使用的主题可以通过 Application.UserAppTheme 属性进行设置,该属性的类型为 OSAppTheme,无论当前运行的是哪个系统主题:

Application.Current.UserAppTheme = OSAppTheme.Dark;

在此示例中,应用程序设置为使用为系统深色模式定义的主题,无论当前运行哪个系统主题。

注意

UserAppTheme 属性设置为 OSAppTheme.Unspecified,以默认使用可运行的系统主题。

对主题更改作出响应

设备上的系统主题可能会因各种原因而发生更改,具体取决于设备的配置方式。 通过处理 Application.RequestedThemeChanged 事件,系统主题更改时可以通知 Xamarin.Forms 应用:

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

RequestedThemeChanged 事件附带的 AppThemeChangedEventArgs 对象有一个名为 RequestedTheme 的属性,其类型为 OSAppTheme。 可以检查此属性,以检测请求的系统主题。

重要

若要响应 Android 上的主题更改,必须在 MainActivity 类的 Activity 属性中包含 ConfigChanges.UiMode 标志。