本文主要說如何在UWP切換主題,并且如何制作主題。
一般我們的應用都要有多種顔色,一種是正常的白天顔色,一種是晚上的黑夜顔色,還需要一種輔助的高對比顔色。這是微軟建議的,一般應用都要包含的顔色。
我們還可以自己定義多種顔色,例如金屬、海藍之光、彩虹雨。然而微軟給我們的切換,簡單隻有亮和暗。
那麼問題就是我們如何切換我們的主題。
在這前,我們先說如何制作主題,其實主題就是Dictionary,我們在解決方案加上兩個檔案夾,一個是View,一個是ViewModel,其中View将會放主題,如果主題比較多,還可以在View加一個檔案夾。
首先在View檔案夾建立資源
我根據原文說的建立幾個資源叫LightThemeDictionary、DarkThemeDictionary,一個是白天顔色,一個是黑暗
然後我們在我們的資源寫入幾個資源
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NightDayThemeToggleButton.View">
<SolidColorBrush x:Key="SystemBackgroundAltHighBrush" Color="#FFF0F0F0"/>
<SolidColorBrush x:Key="SystemBackgroundBaseHighBrush" Color="#FF101010"/>
<Color x:Key="SystemTranslucentBaseHighColor">#FF000000</Color>
<Color x:Key="SystemThemeMainColor">#FF0074CE</Color>
</ResourceDictionary>
複制
然後在黑暗也寫相同key的資源
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NightDayThemeToggleButton.View">
<SolidColorBrush x:Key="SystemBackgroundAltHighBrush" Color="#FF1A1C37"/>
<SolidColorBrush x:Key="SystemBackgroundBaseHighBrush" Color="#FFDFDFDF"/>
<Color x:Key="SystemTranslucentBaseHighColor">#FFFFFFFF</Color>
<Color x:Key="SystemThemeMainColor">#FF0074CE</Color>
</ResourceDictionary>
複制
然後我們需要在前台把資源放在Page
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light" Source="View/DarkThemeDictionary.xaml"></ResourceDictionary>
<ResourceDictionary x:Key="Dark" Source="View/LightThemeDictionary.xaml"></ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
</ResourceDictionary>
</Page.Resources>
複制
我們使用資源需要ThemeDictionaries,這個是主題
記住要把資源一個叫
x:Key="Light"
一個Dark,原因在下面會說。
我們建立ViewModel,其中ViewModel繼承NotifyProperty,這是一個我寫的類,這個類主要是INotifyPropertyChanged,如果自己寫ViewModel也好
ViewModel建立在ViewModel檔案夾,一般少把類名稱和檔案夾一樣
我們ViewModel主要是屬性
ElementTheme Theme
,ElementTheme 有Default,Light,Dark,就是我們要把key叫light和dark,這樣就可以綁定ViewModel修改
viewModel
public class ViewModel : NotifyProperty
{
public ViewModel()
{
}
public ElementTheme Theme
{
set
{
_theme = value;
OnPropertyChanged();
}
get
{
return _theme;
}
}
private ElementTheme _theme = ElementTheme.Light;
}
複制
我們綁定Page.RequestedTheme
先在xaml.cs寫
private ViewModel.ViewModel View { set; get; }=new ViewModel.ViewModel();
複制
然後在xaml
<Page
x:Class="NightDayThemeToggleButton.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:NightDayThemeToggleButton"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
RequestedTheme="{x:Bind View.Theme,Mode=OneWay}">
複制
我們要看到變化,在xaml使用
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid Background="{ThemeResource SystemBackgroundAltHighBrush}">
<ToggleSwitch HorizontalAlignment="Center" Toggled="ToggleSwitch_OnToggled"></ToggleSwitch>
</Grid>
</Grid>
複制
SystemBackgroundAltHighBrush是我們兩個資源的,其中一個是白天,一個不是
private void ToggleSwitch_OnToggled(object sender, RoutedEventArgs e)
{
View.Theme = View.Theme == ElementTheme.Light ? ElementTheme.Dark :
ElementTheme.Light;
}
複制
運作可以看到點選就變成白天顔色,再點選就變為黑暗,這就是uwp切換主題,這樣主題顔色很少,隻有兩個。
參見:https://embracez.xyz/xaml-uwp-themes/
我們總是會使用白天,夜間模式,那麼我們需要切換主題,UWP切換主題簡單
下面使用我做的一個按鈕
夜間白天主題按鈕
NightDayThemeToggleButton
我做的還有遊戲鍵,這些都是可以簡單使用的控件
這些控件放在https://github.com/lindexi/UWP,大家可以拿下來用。
做一個按鈕,其實是修改
<Style x:Key="NightDayThemeToggleButton" TargetType="CheckBox">
<Setter Property="Background" Value="Transparent"/>
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
<Setter Property="Padding" Value="8,5,0,0"/>
<Setter Property="HorizontalAlignment" Value="Left"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Left"/>
<Setter Property="VerticalContentAlignment" Value="Top"/>
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
<Setter Property="MinWidth" Value="120"/>
<Setter Property="MinHeight" Value="32"/>
<Setter Property="UseSystemFocusVisuals" Value="True"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CheckBox">
<Grid BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CombinedStates">
<VisualState x:Name="UncheckedNormal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="UncheckedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="UncheckedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="UncheckedDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedNormal">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedPressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="CheckedDisabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Light" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="0"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Dark" Storyboard.TargetProperty="Opacity">
<DiscreteObjectKeyFrame KeyTime="0" Value="1"></DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminateNormal">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminatePointerOver">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminatePressed">
<Storyboard>
</Storyboard>
</VisualState>
<VisualState x:Name="IndeterminateDisabled">
<Storyboard>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image x:Name="Light" Source="Assets/weather_sun.png"></Image>
<Image x:Name="Dark" Source="Assets/weather_moon.png"></Image>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
複制
需要使用也簡單,可以使用
<CheckBox Margin="16,193,0,75" Style="{StaticResource NightDayThemeToggleButton}" IsChecked="{x:Bind AreChecked,Mode=TwoWay}"></CheckBox>
複制
這樣複制我上面代碼就好,如果想用我的控件,可以
<local:NightDayThemeToggleButton ></local:NightDayThemeToggleButton>
複制
上面用到兩張圖檔,一張是白天,一張是夜晚
首先我們是編輯副本,不知道這個在哪的可以去看我的入門http://blog.csdn.net/lindexi_gd/article/details/52041944,裡面有很多連接配接
然後我們可以看到
<VisualState x:Name="UncheckedNormal">
複制
我們把下面自帶所有控件都删掉,然後添加兩個Image,當然需要給他們x:Name
接着在上面添加透明度從1到0或從0到1,大概就是這樣做。
UWP 和系統一樣的主題
UWP如果想保持主題和系統一樣,随着系統主題,簡單方法,在App.xaml,删除
RequestedTheme="Light"
因為在UWP,沒有給他一個值,就會和系統一樣,但是在我們app運作,改變系統主題,我們就沒辦法立刻就随着系統改,這個我們不需要去想,因為在之後,垃圾wr自己去弄
http://stackoverflow.com/a/39898422/6116637