UWP中實現自定義標題欄

durow發表於2015-10-21

UWP中實現自定義標題欄

0x00 起因

在UWP開發中,有時候我們希望實現自定義標題欄,例如在標題欄中加入搜尋框、按鈕之類的控制元件。搜了下資料居然在一個日文網站找到了一篇介紹這個主題的文章:

http://www.atmarkit.co.jp/ait/articles/1510/14/news022.html

看了下本想著翻譯過來分享,但有些地方說的不是特別明確,所以自己實現了下,結合自己的體會總結了這篇文章。

0x01 UWP中的標題欄

一個普通的UWP視窗如下圖所示:

 

我們可以通過兩種方式獲取不同的標題欄物件,不同物件操作側重點不同。

var coreTitleBar = Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().TitleBar;

這種方式獲取的是一個CoreApplicationViewTitleBar物件,主要控制標題欄擴充套件等相關功能。後面的coreTitleBar指的就是這個物件。

var appTitleBar = Windows.UI.ViewManagement.ApplicationView.GetForCurrentView().TitleBar;

這種方式獲取的是一個ApplicationViewTitleBar物件,主要用於控制標題欄背景色,最小化、最大化、關閉等按鈕的顏色、背景色等。後面的appTitleBar指的就是這個物件。

我們自定義標題欄時這兩個物件都會用到。

0x02 實現自定義標題欄

coreTitleBar中有一個屬性為ExtendViewIntoTitleBar,將其設定為true就允許將我們在窗體中用XAML定義的檢視擴充套件至標題欄區域

coreTitleBar.ExtendViewIntoTitleBar = true;

這個設定後標題欄原有的地方就消失了,我們定義的試圖擴充套件了過去,如下圖所示:

 

看上去離我們的目標近了一些,標題欄消失了,我們在XAML中定義的Grid上移佔據了原有標題欄的位置,原有的appTitleBar上的最大化、最小化、關閉按鈕都可用。如果只是一副圖片擴充套件至標題欄用作背景的話貌似可以了,不過我們希望在標題欄上加個搜尋欄,所以還是存在幾個問題的:

appTitleBar的背景色不協調。

要解決這個問題,我們需要把appTitleBar上按鈕的背景色設定為透明:

appTitleBar.ButtonBackgroundColor = Colors.Transparent;

設定後窗體就變成這樣了:

 

按鈕背景色變成了透明,但系統標題欄上的按鈕和我們自定義標題欄上的搜尋框重疊了。要解決這個問題我們可以利用coreTitleBar上的屬性SystemOverlayLeftInset和SystemOverlayRightInset,分別表示了coreTitleBar嵌入時的左邊距和右邊距,我們可以通過設定自定義標題欄的Padding屬性達到目的:

//TitleBar為我們自己的標題欄
TitleBar.Height = coreTitleBar.Height;
TitleBar.Padding = new Thickness(
    coreTitleBar.SystemOverlayLeftInset,
    0,
    coreTitleBar.SystemOverlayRightInset,
    0 );

那麼在什麼時候進行這個設定比較好呢,coreTitleBar有一個事件叫做LayoutMetricsChanged,當頁面佈局發生變化時觸發,例如螢幕旋轉導致頁面重新佈局就會觸發這個事件。我們可以吧標題欄Padding屬性的設定放在這個事件裡。設定好後執行程式標題欄如下圖所示:

 

這樣似乎好多了,但是當我想在搜尋欄輸入點內容時發現根本點不進去啊,放大鏡按鈕也沒法點,按住搜尋欄還能拖動視窗,看來是我們自己的標題欄被系統標題欄遮擋在下面了。

 

大概就是上圖這麼一種感覺。

對於這個問題,我們可以使用Window物件中的SetTitleBar()方法只把文字區域設定為標題欄:

Window.Current.SetTitleBar(TitleText);

其中TitleText是我們自定義標題欄中的文字控制元件的區域,這個方法就把TitleText這個控制元件設定為了標題欄。效果就是TitleText控制元件可以拖動窗體,雙擊可以最大化/恢復等。這樣其他需要接收輸入的控制元件就不屬於標題欄,就可以正常接收輸入了。

另外我還考慮了一種方式就是重疊兩層Grid,底層通過SetTitleBar設定為標題欄,放置不需要接收輸入的控制元件如文字、圖片等,上層放置需要接收輸入的控制元件,如TextBox等,不過沒有實際測試。

除此之外還可以考慮給標題欄加入返回按鈕,按鈕呼叫Frame.GoBack()方法,根據Frame.CanGoBack屬性決定返回按鈕是否顯示。這個也很容易實現,就不作說明了。

程式最後執行效果如圖所示,其中手機終端本身就不顯示標題欄

0x03 相關下載

https://github.com/durow/TestArea/tree/master/UWPTest/TitleBarTest

 


更多內容歡迎訪問我的部落格:http://www.durow.vip

相關文章