(UWP)應用窗口實現毛玻璃效果

雜想

最近微軟在開Build2017大會,為期三天。目前修仙看了兩晚的大會直播,第一晚的主角是Azure云服務以及Cortana人工智能,有很多很不錯的點子;第二晚終于講到了Windows,這才是我迫不及待想知道的啊。微軟在Build2017宣布了Windows 10的下一個更新:Windows 10 Fall Creators Update。我印象很深的幾個新特性是:

  1. 新的Story Teller應用,集成了AI技術,可以識別出故事人物,并按照選擇的主角生成精彩的視頻。結合混合現實技術,可以加入一些很酷炫的3D模型(比如恐龍)和特效。
  1. TimeLine,顯示最近的工作
  2. 新的Fluent Design System,包含五個元素:Light(光感)、Depth(深度)、Motion(動效)、Material(材質)、Scale(縮放)
  3. 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的。


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);`

好啦現在運行試試。

![右上角!](http://upload-images.jianshu.io/upload_images/4846400-fde9ead5526bdc13.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

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

現在,效果如下圖所示~
![只使用毛玻璃筆刷的效果](http://upload-images.jianshu.io/upload_images/4846400-aaece2e51dbfe129.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

####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%為不透明,這樣就可以啦。教程部分就結束啦。
![透明度設置](http://upload-images.jianshu.io/upload_images/4846400-629745d20f765375.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)

#后記
其實很希望已經在應用商店上傳應用的開發者盡快用新的規范去更新完善自己的UWP應用。而我,還在學習階段。很是希望,自己能盡快開發出一款高質量的App。說是教程,其實也不會太多人看啦,UWP開發在我們學校也真的算是冷門,而我也是因為個人興趣才有一點點動力去研究。那,這教程就算是寫給自己看的吧:-)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,327評論 6 537
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,996評論 3 423
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,316評論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,406評論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,128評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,524評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,576評論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,759評論 0 289
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,310評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,065評論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,249評論 1 371
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,821評論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,479評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,909評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,140評論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,984評論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,228評論 2 375

推薦閱讀更多精彩內容