以今天的眼光來看,一個好應用首先是要有好的用戶體驗。而好的用戶體驗最直觀的就來自於用戶界面。好的用戶界
面則需要好的設計,更需要好的實現。今天我們就向大家分享一下我們在使用Xaml實現界面設計上的一點心得。
樣式管理
我們拿到的設計,大多是一張紅線圖,佈滿了距離,字號,色號,事無鉅細的量化了我們的用戶界面。如果我們就這
樣把各種屬性照搬到上Xaml文件中,那看起來就非常不妙了,比如這樣:
<TextBlock Text="首頁"FontFamily =" Segoe WP "FontSize ="24"FontWeight =" Normal "TextTrimming =" CharacterEllipsis "TextWrapping =" Wrap "MaxLines ="2" Foreground="#FF297ACD " ></TextBlock>
一個看起來還好,但是通常我們的頁面上不可能只有這一個控件。要是有上10個20個,那如果要修改其中一個屬性
可真是得看花了眼啊。
很幸運,我們在Universal應用的開發中可以把控件的相同屬性歸納爲資源(Resource),再在需要的時候應用到控
件上就可以了。
有些很重要的單獨的屬性,以顏色爲例,不同控件都會使用,卻只有幾個值,Universal應用可以把它單獨抽象成一種
StaticResource 資源--Brush 。將它應用到控件的 Foreground 或者Background 之類的屬性上時,就會
像"brush(刷子)"一樣把控件變爲它的顏色。其中常用的SolidColorBrush 可以寫成這樣:
<SolidColorBrush x:Key=" PostTitleFont" Color="#FF297ACD"/>
將它放到資源字典或者頁面的<Page.Resources> 中,就可以通過{StaticResource Brush的x:Key的值} 的形式來應
用了。
而同一種控件的多個相同屬性,我們可以把它們歸納成Style這種StaticResource資源,存在當前頁面的
<Page.Resources> 中:
<Page.Resources>
<SolidColorBrush x:Key=" PostTitleFont" Color="#FF297ACD"/>
<Style x:Key="PostTitleFont" TargetType="TextBlock">
<Setter Property="FontFamily" Value="Segoe WP"/>
<Setter Property="FontSize" Value="24"/>
<Setter Property="FontWeight" Value="Normal"/>
<Setter Property="TextTrimming" Value="CharacterEllipsis"/>
<Setter Property="TextWrapping" Value="Wrap"/>
<Setter Property="MaxLines" Value="2"/>
<Setter Property="Foreground" Value="{StaticResourcePostTitleFont }"/>
</Style>
</Page.Resources>
Style 的 TargetType 屬性指明瞭Style可以應用的元素,比如TargetType="TextBlock" 的Style是不能應用到Image
元素上的。而Style中包含的就是要應用的屬性了,以 <Setter Property="屬性名" Value="屬性值"/> 這樣的形式。
那麼我們在當前頁面的需要應用Sytle的地方,比如上面的情況,就只需要通過Style的x:Key 屬性來應用:
<TextBlock Text="首頁" Style="{StaticResource PivotTitleFont}"></TextBlock>
我們可以看到 Style="{StaticResource PivotTitleFont}" 中的 PivotTitleFont 就是 Style的 x:Key 屬性,這樣style就
能夠應用到 TextBlock 上了。
而且Style還能繼承。比如我要一個 PostSubTitleFont, 只要字體比PostTitleFont 小一點。那我就可以這麼寫:
<Style x:Key="PostSubTitleFont" TargetType="TextBlock" BasedOn="{StaticResource PostTitleFont}">
<Setter Property="FontSize" Value="20"></Setter>
</Style>
這樣一來如果我想改動它們的字體,只要在PostTitleFont中修改就可以了。是不是很方便?
當然我們通常也不止有一個頁面,如果不想在每個頁面中都把 Style 和 Brush 都貼一遍,就需要資源字典文件出場
了。在我們的項目中添加一個資源字典文件:
再把我們的Style和 Brush都寫在裏面。然後在需要使用這些Style和 Brush的頁面添加形如下面的代碼把資源詞典引
用上就可以啦:
<Page.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Page.Resources>
當然,我們既然是Universal應用,能不能把Styl和 Brushe在Windows應用和Windows Phone應用間共享呢?答案
是可以的。我們只要把資源文件放在.share項目下面,再在App.xaml中添加它的引用就可以:
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
這樣Dictionary.xaml中的Style和 Brush就在Windows應用和Windows Phone應用的所有頁面都有效了。
等等,那Windows應用和Windows Phone應用間有所區別的Style和 Brush怎麼辦呢?
也有辦法。只要在Windows項目和Windows Phone項目中各添加一個同名的資源詞典文件比如
DifferentDictionary.xaml,把不同的Style和 Brush寫入,再在App.xaml中引用就能夠實現了。
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="Dictionary.xaml" />
<ResourceDictionary Source="DifferentDictionary.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
這樣,我們通過Resource 和資源詞典文件大大簡化了用戶界面設計的實現過程,是不是很方便呢?
夜間模式
說到閱讀軟件的用戶體驗,就不得不提到夜間模式了。下面就說說我們在Windows Phone應用上實現夜間模式的過
程吧。
大家可能都在Windows Phone 設置的 開始屏幕+主題 中設置過背景和主題色,當我們修改了背景的 黑/白 後,幾乎
所有的系統應用的背景色和文字的顏色都立刻改變了,連重啓應用都不用。
我們實現的夜間模式正是利用了這個功能。
在Windows Phone應用中,如果我們設置了當前 Page的 RequestedTheme 屬性爲Light 或者Dark的話就相當於我
們在系統設置裏修改了背景黑/白。比如通常情況下我們新建一個應用,默認的情況下都是黑底白字:
而如果我們把Page的 RequestedTheme 屬性設爲的話,可以看到在設計視圖中應用變成了白底黑字:
那麼我們通過settings頁面的一個 ToggleSwitch控件實時切換RequestedTheme這一屬性,就可以實時控制應用的
各種顏色如背景色,文字顏色爲Light或Dark對應的顏色。我們把Light設爲日間模式,Dark設爲夜間模式。簡單一
點的情況下可以把 ToggleSwitch 的Toggled事件響應方法設爲如下:
private void ts_LightMode_Toggled(object sender, RoutedEventArgs e)
{
if (this.RequestedTheme == ElementTheme.Light)
{
this.RequestedTheme = ElementTheme.Dark;
}
else
{
this.RequestedTheme = ElementTheme.Light;
}
}
接下來如何設置日間模式/夜間模式對應的顏色呢?
在之前的樣式管理一節中我們提到了通過{StaticResource PivotTitleFont } 的形式來應用 SolidColorBrush 資源,但
是我們在資源 PostTitleFont 定義的時候只寫了一個值,系統會自動幫我們轉換麼?事實上並沒有那麼簡單。我們需
要通過 ThemeResource 類型的資源預先設置好2種模式對應的顏色。應用了這種 ThemeResource 資源以後,這個
控件就能夠響應 RequestedTheme 屬性的變化,即時切換顯示對應模式的顏色。
那麼怎樣加入這種資源呢?我們可以打開我們的資源字典 Dictionary.xaml ,在裏面加入這樣一段代碼:
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
這裏 x:Key 分別爲Dark/ Light 的 ResourceDictionary 中,就是我們存放對應兩種模式的資源的地方。比如我們希
望頁面背景在日間模式下是 藍色,夜間模式下是深灰色,就可以這麼寫:
<ResourceDictionary.ThemeDictionaries>
<ResourceDictionary x:Key="Light">
<SolidColorBrush x:Key="myPageBackground" Color="Blue"></SolidColorBrush>
</ResourceDictionary>
<ResourceDictionary x:Key="Dark">
<SolidColorBrush x:Key="myPageBackground" Color="DarkGray"></SolidColorBrush>
</ResourceDictionary>
</ResourceDictionary.ThemeDictionaries>
在我們的page中就可以這樣應用 ThemeResource 資源了:
<Page
x:Class="my_universal.CnblogsMainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:my_universal"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
RequestedTheme="Light"
Background="{ThemeResourcemyPageBackground }">
是不是一點都不難呢?
另外我們還發現有兩點值得注意:
一是我們可以覆蓋系統的 ThemeResource 。我們可以選中任意一個 TextBlock 控件,打開屬性欄,選Foreground
屬性的畫筆資源。
可以看到下方以ThemeBrush結尾的都是系統的 ThemeResource 資源,只要在我們的 x:Key 分別爲Dark/ Light 的
ResourceDictionary 里加入和它們同名的資源,就能夠覆蓋它們了。
二是對於Flyout 類型的控件,應用到它上面的 ThemeResource 資源是相反的。就是說當RequestedTheme 屬性爲
Light 時,Flyout 類型的控件會應用 Dark ResourceDictionary 中的資源。反之亦然。