如何在 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}}">
我更新了 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}}">