问题描述
我更新了Visual Studio,现在我的程序主题与手机上的主题相同,电话上的内容暗了,我希望程序变亮,请帮忙,我尝试了Application.Current.UserAppTheme = OSAppTheme.Light,但不起作用
解决方法
您可以使用AppThemeBinding
设置浅色主题或深色主题。
从下面的链接下载源文件并进行一些更改。 https://docs.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/userinterface-systemthemesdemo/
当您在手机上设置暗模式并希望程序变亮时,您可以如下更改xaml:
更改: ContentPage BackgroundColor
BackgroundColor="{AppThemeBinding Light={StaticResource LightPageBackgroundColor},Dark={StaticResource DarkPageBackgroundColor}}">
收件人:
BackgroundColor="{AppThemeBinding Light={StaticResource DarkPageBackgroundColor},Dark={StaticResource LightPageBackgroundColor}}">
更改::网格BackgroundColor
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource LightPrimaryColor},Dark={StaticResource DarkPrimaryColor}}">
收件人:
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource DarkPrimaryColor},Dark={StaticResource LightPrimaryColor}}">
,
动态更改属性
第一步是将将受主题更新影响的每个视图属性交换为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</On>
<On Platform="Android">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这样的样式来定义它。 例如,在xaml中的任何地方都没有定义DynamicBackgroundColor,您可以将它们视为等待分配的引用。
您可以像这样在代码中动态分配它们(之后我们将看到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,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";
}