天天看點

win10 uwp 切換主題

本文主要說如何在UWP切換主題,并且如何制作主題。

一般我們的應用都要有多種顔色,一種是正常的白天顔色,一種是晚上的黑夜顔色,還需要一種輔助的高對比顔色。這是微軟建議的,一般應用都要包含的顔色。

我們還可以自己定義多種顔色,例如金屬、海藍之光、彩虹雨。然而微軟給我們的切換,簡單隻有亮和暗。

那麼問題就是我們如何切換我們的主題。

在這前,我們先說如何制作主題,其實主題就是Dictionary,我們在解決方案加上兩個檔案夾,一個是View,一個是ViewModel,其中View将會放主題,如果主題比較多,還可以在View加一個檔案夾。

win10 uwp 切換主題

首先在View檔案夾建立資源

win10 uwp 切換主題

我根據原文說的建立幾個資源叫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