【发布时间】:2020-08-14 14:10:39
【问题描述】:
我更新了visual studio,现在程序的主题和手机上的一样,手机上是暗的,我想让程序亮一点,请帮忙,我试过Application.Current.UserAppTheme = OSAppTheme.Light,但它不起作用
【问题讨论】:
标签: c# xamarin xamarin.forms xamarin.android themes
我更新了visual studio,现在程序的主题和手机上的一样,手机上是暗的,我想让程序亮一点,请帮忙,我试过Application.Current.UserAppTheme = OSAppTheme.Light,但它不起作用
【问题讨论】:
标签: c# xamarin xamarin.forms xamarin.android themes
您可以使用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}}">
更改:网格背景颜色
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource LightPrimaryColor}, Dark={StaticResource DarkPrimaryColor}}">
收件人:
<Grid BackgroundColor="{AppThemeBinding Light={StaticResource DarkPrimaryColor}, Dark={StaticResource LightPrimaryColor}}">
【讨论】:
动态更改属性
第一步是将受主题更新影响的每个视图属性都替换为静态资源。 这样做,例如,当您将 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";
}
【讨论】: