如何在 Xamarin Forms 中使用 Light Theme?

How to use Light Theme in Xamarin Forms?

我更新了 visual studio,现在我的程序主题与 phone 上的相同,phone 上是黑色的,我希望程序轻点,请帮忙,我试过Application.Current.UserAppTheme = OSAppTheme.Light,但它不起作用

动态更改属性

第一步是将 StaticResource 换成 DynamicResource,每个视图属性都会受到主题更新的影响。 这样做,例如当您将 DynamicBackgroundColor 从黑色设置为白色时,它将自动传播到引用此键的所有属性。

让我们看看我们的 App.xaml:

<Color x:Key="DarkSurface">#121212</Color>  
<Color x:Key="LightSurface">#00FF0266</Color>

...

<Style ApplyToDerivedTypes="True" TargetType="ContentPage">  
<Setter Property="Padding">
    <Setter.Value>
        <OnPlatform x:TypeArguments="Thickness">
            <On Platform="iOS">0, 20, 0, 0</On>
            <On Platform="Android">0, 0, 0, 0</On>
        </OnPlatform>
    </Setter.Value>
</Setter>
<Setter Property="BackgroundColor" Value="{DynamicResource DynamicBackgroundColor}" />
</Style>

<Style ApplyToDerivedTypes="True" TargetType="NavigationPage">  
    <Setter Property="BarBackgroundColor" Value="{DynamicResource 
                                                   DynamicNavigationBarColor}" />
    <Setter Property="BarTextColor" Value="{DynamicResource DynamicBarTextColor}" />
</Style>  

我们可以看到 DynamicResource 也适用于样式...

DynamicResource 值的问题在于您不会像经典 StaticResource 那样在您的样式中定义它。 例如DynamicBackgroundColor在xaml的任何地方都没有定义,你可以把它们看成是等待分配的引用。

您可以像这样在代码中动态分配它们(之后我们将立即看到 SetDynamicResource 实现):

// Dark Mode
SetDynamicResource(DynamicBackgroundColor, "DarkSurface");

// Ligh Mode
SetDynamicResource(DynamicBackgroundColor, "LightSurface"); 

在明暗模式之间切换

在我愚蠢的应用程序中!底部栏我有一个带有切换主题图标的 TabButton,单击它会调用 SetDarkMode() 或 SetLightMode():

namespace SillyCompany.Mobile.Practices.Presentation.Views{
   public static class ResourcesHelper{
        public const string DynamicPrimaryTextColor = nameof(DynamicPrimaryTextColor);
        public const string DynamicSecondaryTextColor = nameof(DynamicSecondaryTextColor);

        public const string DynamicNavigationBarColor = nameof(DynamicNavigationBarColor);
        public const string DynamicBackgroundColor = nameof(DynamicBackgroundColor);
        public const string DynamicBarTextColor = nameof(DynamicBarTextColor);

        public const string DynamicTopShadow = nameof(DynamicTopShadow);
        public const string DynamicBottomShadow = nameof(DynamicBottomShadow);

        public const string DynamicHasShadow = nameof(DynamicHasShadow);

        public const string Elevation4dpColor = nameof(Elevation4dpColor);

        ...

        public static void SetDynamicResource(string targetResourceName, string sourceResourceName)
    {
        if (!Application.Current.Resources.TryGetValue(sourceResourceName, out var value))
        {
            throw new InvalidOperationException($"key {sourceResourceName} not found in the resource dictionary");
        }

          Application.Current.Resources[targetResourceName] = value;
      }

      public static void SetDynamicResource<T>(string targetResourceName, T value)
      {
          Application.Current.Resources[targetResourceName] = value;
      }

      public static void SetDarkMode()
      {
           MaterialFrame.ChangeGlobalTheme(MaterialFrame.Theme.Dark);
           SetDynamicResource(DynamicNavigationBarColor, "DarkElevation2dp");
           SetDynamicResource(DynamicBarTextColor, "TextPrimaryDarkColor");

           SetDynamicResource(DynamicTopShadow, ShadowType.None);
           SetDynamicResource(DynamicBottomShadow, ShadowType.None);
           SetDynamicResource(DynamicHasShadow, false);

           SetDynamicResource(DynamicPrimaryTextColor, "TextPrimaryDarkColor");
           SetDynamicResource(DynamicSecondaryTextColor, "TextSecondaryDarkColor");

           SetDynamicResource(DynamicBackgroundColor, "DarkSurface");

           SetDynamicResource(Elevation4dpColor, "DarkElevation4dp");
       }

       public static void SetLightMode(){
           MaterialFrame.ChangeGlobalTheme(MaterialFrame.Theme.Light);
           SetDynamicResource(DynamicNavigationBarColor, "Accent");
           SetDynamicResource(DynamicBarTextColor, "TextPrimaryDarkColor");

           SetDynamicResource(DynamicTopShadow, ShadowType.Top);
           SetDynamicResource(DynamicBottomShadow, ShadowType.Bottom);
           SetDynamicResource(DynamicHasShadow, true);

           SetDynamicResource(DynamicPrimaryTextColor, "TextPrimaryLightColor");
           SetDynamicResource(DynamicSecondaryTextColor, "TextSecondaryLightColor");

           SetDynamicResource(DynamicBackgroundColor, "LightSurface");

           SetDynamicResource(Elevation4dpColor, "OnSurfaceColor");
        }
   }
}

你可以看到我不仅改变了颜色,而且在黑暗模式下禁用了阴影,因为黑暗模式本质上是平坦的。

示例:SillyBottomTabsPage.cs

<tb:Toolbar x:Name="Toolbar"  
        Title="Silly App!"
        BackgroundColor="{DynamicResource DynamicNavigationBarColor}"
        ForegroundColor="White"
        HasShadow="{DynamicResource DynamicHasShadow}"
        Subtitle="The Official sample app for the Sharpnado's components" />

...

<tabs:TabHostView   x:Name="TabHost"  
                Grid.Row="2"
                BackgroundColor="{DynamicResource Elevation4dpColor}"
                ShadowType="{DynamicResource DynamicTopShadow}"
                TabType="Fixed"
                SelectedIndex="{Binding Source={x:Reference Switcher}, 
Path=SelectedIndex, Mode=TwoWay}">

<tabs:TabButton x:Name="TabButton"
                IsVisible="True"
                ButtonBackgroundColor="{StaticResource Accent}"
                ButtonCircleSize="60"
                ButtonPadding="15"
                IconImageSource="theme_96.png"
                Scale="1.3"
                TranslationY="-10"
                Clicked="TabButtonOnClicked" />

...

进行转换 现在让我们看看转换的代码:

SillyBottomTabsPage.xaml.cs

private void TabButtonOnClicked(object sender, EventArgs e){
    TaskMonitor.Create(AnimateTabButton);
}

private void ApplyTheme(){

   if (_currentTheme == Theme.Light) {
        ResourcesHelper.SetLightMode();
        return;
   }

   ResourcesHelper.SetDarkMode();
}

private async Task AnimateTabButton(){

    double sourceScale = TabButton.Scale;
    Color sourceColor = TabButton.ButtonBackgroundColor;
    Color targetColor = _currentTheme == Theme.Light
    ? ResourcesHelper.GetResourceColor("DarkSurface")
    : Color.White;

    // Bounce then remove icon from button,
    await TabButton.ScaleTo(3);
    await TabButton.ScaleTo(sourceScale);
    TabButton.IconImageSource = null;

    // Ballon inflation
    var bigScaleTask = TabButton.ScaleTo(30, length: 500);
    // Change color to target dark/light mode
    var colorChangeTask = TabButton.ColorTo(
    sourceColor,
    targetColor,
    callback: c => TabButton.ButtonBackgroundColor = c,
    length: 500);

    // run animation at the same time
    await Task.WhenAll(bigScaleTask, colorChangeTask);

    _currentTheme = _currentTheme == Theme.Light ? Theme.Dark : Theme.Light;
    ApplyTheme();

    // reverse inflation and color animation to accent color
    var reverseBigScaleTask = TabButton.ScaleTo(sourceScale, length: 500);
    var reverseColorChangeTask = TabButton.ColorTo(
    targetColor,
    sourceColor,
    c => TabButton.ButtonBackgroundColor = c,
    length: 500);

    await Task.WhenAll(reverseBigScaleTask, reverseColorChangeTask);

    // icon is back
    TabButton.IconImageSource = "theme_96.png";
}

您可以使用AppThemeBinding设置浅色主题或深色主题。

从下面的link下载源文件并做一些修改。 https://docs.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/userinterface-systemthemesdemo/

当您在 phone 上设置暗模式并希望程序为亮模式时,您可以像下面这样更改 xaml:

更改: ContentPage 背景颜色

 BackgroundColor="{AppThemeBinding Light={StaticResource LightPageBackgroundColor}, Dark={StaticResource DarkPageBackgroundColor}}">

收件人:

 BackgroundColor="{AppThemeBinding Light={StaticResource DarkPageBackgroundColor}, Dark={StaticResource LightPageBackgroundColor}}">

更改: 网格背景颜色

 <Grid BackgroundColor="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}">

收件人:

 <Grid BackgroundColor="{AppThemeBinding Light={StaticResource DarkPrimaryColor}, Dark={StaticResource LightPrimaryColor}}">