雜想
最近微軟在開Build2017大會,為期三天。目前修仙看了兩晚的大會直播,第一晚的主角是Azure云服務以及Cortana人工智能,有很多很不錯的點子;第二晚終于講到了Windows,這才是我迫不及待想知道的啊。微軟在Build2017宣布了Windows 10的下一個更新:Windows 10 Fall Creators Update。我印象很深的幾個新特性是:
- 新的Story Teller應用,集成了AI技術,可以識別出故事人物,并按照選擇的主角生成精彩的視頻。結合混合現實技術,可以加入一些很酷炫的3D模型(比如恐龍)和特效。
- TimeLine,顯示最近的工作
- 新的Fluent Design System,包含五個元素:Light(光感)、Depth(深度)、Motion(動效)、Material(材質)、Scale(縮放)
- Win10內置的Linux環境得到增強,應用商店還可以直接下載Ubuntu等Linux發行版
其實我是一個很在意UI的人,所以以上最令我振奮的就是Fluent Design了。微軟其實不缺好的UI設計理念,Windows Vista開始的Aero,Windows 8的Metro都很棒,不過到了Windows 10,感覺微軟應該在UI上更進一步的。Fluent Design讓我看到了曙光,我喜歡這個設計規范。早在年初,Fluent Design就以內部代號Project Neon被曝光,然后有人發現了微軟開放了窗體毛玻璃透明相關的Apis。調用這些Apis,我們就可以做出帶有部分Fluent Design風格的UWP應用了。當然,我相信微軟在最近會更新更多的Apis來方便開發者實現Fluent Design的。
參考
主要參考了IT之家的兩篇教程
Win10 UWP開發技巧:應用窗口實現毛玻璃效果
Win10 UWP開發技巧:充分利用標題欄空間
另外為了實現一些自己想要的效果動了點小腦筋:-)
窗體效果
教程
注:本教程只實現窗體的半透明,關于窗口內控件元素的半透明以后再說╮(╯▽╰)╭
實現窗體半透明用到的筆刷需要用到15021以后的SDK,所以要將項目的目標平臺設置為超過15021的版本
1. 隱藏標題欄
原理
在這個頁面的構造函數里通知框架,把布局擴展至標題欄,框架就會去掉原來的標題欄,并把我們編寫的布局擴展填充至屬于標題欄的那一部分區域。我們還可以通知框架,我們自己編寫的布局里,有哪一塊依然需要充當標題欄的功能(響應鼠標的拖動、右擊和雙擊等標題欄操作),這樣框架就會將那一塊作標題欄處理。
方法
雙擊解決方案管理器里面的MainPage.xaml,按F7跳轉到MainPage.xaml.cs
首先需要在上方添加對Windows.ApplicationModel.Core和Windows.ApplicationModel.Core的引用:
using Windows.ApplicationModel.Core;
using Windows.UI.ViewManagement;```
然后在構造函數MainPage()里添加以下代碼:
```var coreTitleBar = CoreApplication.GetCurrentView().TitleBar;
coreTitleBar.ExtendViewIntoTitleBar = true;```
那么當這個頁面構造的時候,就會把窗口內容擴展填充到標題欄啦。
這時候你試著運行這個應用,看到的應該是一片慘白的窗口,上面什么也沒有,就連上面的標題欄都消失啦。當你試圖拖曳窗口時發現是可以拖的!不過區域僅限于原來標題欄的位置。原因是我們沒有調用Window.Current.SetTitleBar()這個方法來指定哪個部分是實際的標題欄,那就默認是原來的區域實現標題欄的功能啦。
####2. 使窗體半透明化
轉到MainPage.xaml,在工程剛建的時候,這個xaml文件里面已經默認有一個Grid控件了,默認將它當作根的布局框架。我們為了使用筆刷,要給這個Grid起個名字,在Grid后面輸入x:Name="GlassHost",使這個標簽如下面所示:
`<Grid x:Name="GlassHost">`
這就把它命名為GlassHost啦。按F7跳轉到MainPage.xaml.cs,編寫以下方法:
```private void initializeFrostedGlass(UIElement glassHost)
{
Visual hostVisual = ElementCompositionPreview.GetElementVisual(glassHost);
Compositor compositor = hostVisual.Compositor;
var backdropBrush = compositor.CreateHostBackdropBrush();
var glassVisual = compositor.CreateSpriteVisual();
glassVisual.Brush = backdropBrush;
ElementCompositionPreview.SetElementChildVisual(glassHost, glassVisual);
var bindSizeAnimation = compositor.CreateExpressionAnimation("hostVisual.Size");
bindSizeAnimation.SetReferenceParameter("hostVisual", hostVisual);
glassVisual.StartAnimation("Size", bindSizeAnimation);
}```
這個方法的作用就是接收一個UI控件實例,然后把這個控件半透明和背景模。**但是,這個方法是將一個模糊層覆蓋在被處理的控件之上的,所以這個控件上的任何信息、動作都會被覆蓋掉**。因此窗體里面的控件元素,比如按鈕,是不推薦用這個方法使其背景模糊的,不然的話這個按鈕上的文字會被覆蓋,點擊動作也不能夠響應。
創建了方法也要用才行啊,還記得我們剛剛命名為“GlassHost”的Grid嗎?現在我們就可以用這個方法改變它!在構造函數MainPage()里添加以下代碼:
`initializeFrostedGlass(GlassHost);`
好啦現在運行試試。

咦,右上角的窗口按鍵怎么還是有顏色。嗯…它們的外觀屬性是和窗口本身分開的,需要另外設置,不過也不難。繼續在構造函數MainPage()里添加以下代碼:
```var view = ApplicationView.GetForCurrentView();
view.TitleBar.ButtonBackgroundColor = Colors.Transparent; //將標題欄的三個鍵背景設為透明
view.TitleBar.ButtonInactiveBackgroundColor = Colors.Transparent; //失去焦點時,將三個鍵背景設為透明
view.TitleBar.ButtonInactiveForegroundColor = Colors.White; //失去焦點時,將三個鍵前景色設為白色```
現在,效果如下圖所示~

####3. 在模糊層之上布局
這樣做出來的窗口雖然很美,可是沒有內容展示也只能算是花瓶而已啦。我們也能發現只做以上處理的一個缺點就是,窗體是無色的半透明,而我們往往需要的是有色半透明,因為有時候背景太亮而窗口上的字是白色的話,內容就會變得難以識別。從我們最終的效果圖看來,還有一種分區域的效果。下面我們就來看看怎么實現。
轉到MainPage.xaml,我們先了解到一個技巧:在xaml中,控件代碼在下面的控件反而是被顯示在上層的。那么我們就要思考,我們能不能直接將新控件作為Grid“GlassHost”的子控件放在“GlassHost”里面呢?**很遺憾,并不能,上面說過,使用了那個方法會是控件表面覆蓋上透明層,但透明層是相對于窗體背后透明的,而非背后的控件。**所以,我們只能在那個Grid之外而且是它之上(控件層次的上方,代碼的上方)添加其他控件。我的做法是,保留那個Grid作為根Grid,但是**刪掉**對它的命名。然后是xaml的page標簽里面的內容呈現如下:
<Grid> //根Grid
<Grid.ColumnDefinitions> //定義三列,表現三個區域
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="4*"/>
<ColumnDefinition Width="6*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="GlassHost" Grid.ColumnSpan="3"/> //將這個命名為GlassHost,并使其代碼相對于其他控件在最上方
<Grid Background="#4C1E90FF"> //第一列,設置了一個帶透明度的藍色,如何設置下面給圖
<Grid>
<TextBlock Text="Aero" FontSize="20" Margin="0,32,0,0"
Foreground="White" HorizontalAlignment="Center"
Height="Auto" Width="Auto"/>
</Grid>
</Grid>
<Grid Background="#661E90FF" Grid.Column="1"> //第二列,透明度和第一列不同
<Grid>
<TextBlock Text="Pictures" FontSize="20" Margin="50,32,0,0"
Foreground="White" HorizontalAlignment="Left"
Height="Auto" Width="Auto"/>
</Grid>
</Grid>
<Grid Background="#7F1E90FF" Grid.Column="2"> //第三列,透明度不同
<Grid>
<StackPanel Orientation="Horizontal" Margin="50,32,0,0" Height="Auto">
<TextBlock Text="Zune" FontSize="50" FontWeight="Bold"
Foreground="White" HorizontalAlignment="Left"
Height="Auto" Width="Auto"/>
<TextBlock Text="Y" FontSize="50" Margin="10,0,0,0"
Foreground="White" HorizontalAlignment="Left"
Height="Auto" Width="Auto"/>
</StackPanel>
</Grid>
</Grid>
</Grid>
以上的代碼為無色的模糊層覆蓋上了不同透明度的藍色,這樣可以使得背景更為淡化而不影響閱讀,還能較美觀地區分不同區域。下面來說說透明度是怎樣通過VS的可視化工具設置的。選擇你要調整的Grid,VS右下區域會出現它的屬性控制,選擇畫筆中的Background,調好了自己想要的顏色后,在箭頭所指的A的輸入框輸入透明度,0為全透明,100%為不透明,這樣就可以啦。教程部分就結束啦。

#后記
其實很希望已經在應用商店上傳應用的開發者盡快用新的規范去更新完善自己的UWP應用。而我,還在學習階段。很是希望,自己能盡快開發出一款高質量的App。說是教程,其實也不會太多人看啦,UWP開發在我們學校也真的算是冷門,而我也是因為個人興趣才有一點點動力去研究。那,這教程就算是寫給自己看的吧:-)