將 UWP 中 CommandBar 的展開方向改為向下展開


 

在 UWP 中使用 CommandBar 來迅速添加一組功能按鈕是非常迅速的,是 UWP 中推薦的交互方案之一。也許你能見到 CommandBar 按你所需向下展開,不過可能更多數情況會看到 CommandBar 的展開方向是向上的。

本文將解釋 CommandBar 的展開方向邏輯,並且提供多種方法來解決它展開方向的問題。


 

 

為什么我們需要更改 CommandBar 的展開方向?

<CommandBar Background="#40000000" ClosedDisplayMode="Compact">
    <AppBarButton Icon="Add" Label="添加" ToolTipService.ToolTip="添加一個 RSS 訂閱" />
    <AppBarButton Icon="Bullets" Label="編輯" ToolTipService.ToolTip="進入編輯狀態" />
</CommandBar>

看下圖的例子,我們有一個在頂部的 CommandBar,但是它展開的時候方向是向上的,以至於擋住了頂部的標題欄。

CommandBar 在不合適的方向展開
▲ CommandBar 在不合適的方向展開

理論上標題欄是擋不住的。不過,由於流暢設計(Fluent Design)的存在,越來越多的應用開始使用自定義的標題欄,以獲得渾然天成的流暢設計效果。而上圖就是其中的一個例子。

我們當然希望在頂部的 CommandBar 其展開方向是向下,所以我們需要找到一些方法。

將 CommandBar 改為向下展開的幾種方法

首先定一個基調:CommandBar 的默認展開方向就是向上,無論你使用哪種方式,本質上都沒有解決其展開方向的問題。

所以以下方法都有可能在你的使用場景下失效,除了大殺器 —— 重寫 Template。

方法一:使用 Page.TopAppBar 屬性

<Page x:Class="Walterlv.Rssman.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Page.TopAppBar>
        <CommandBar Background="#40000000" ClosedDisplayMode="Compact">
            <AppBarButton Icon="Add" Label="添加" ToolTipService.ToolTip="添加一個 RSS 訂閱" />
            <AppBarButton Icon="Bullets" Label="編輯" ToolTipService.ToolTip="進入編輯狀態" />
        </CommandBar>
    </Page.TopAppBar>
    <Grid>
    </Grid>
</Page>

如果你並沒有做一些奇怪的樣式,是一個 Demo 或者是剛開始做的應用,那么此方法應該對你有效。

Page.TopAppBar 中的 CommandBar
▲ Page.TopAppBar 中的 CommandBar

看!現在 CommandBar 向下展開了。這就是我們的解決方案之一。

不過,覺得怪怪的是不是?因為我自定義了標題欄,當然不能讓標題欄擋住我的控件啊!

千萬不要嘗試將你的 Page 設置一個 Margin 讓他下移,因為:

Page.TopAppBar 是應用窗口級別的

▲ 無論你設置到哪個 Page 中,無論 Margin 設為多少,就算是給 Frame 外面的 Grid 設置 Margin,通通都是無效的!Page.TopAppBar 在應用窗口級別的。

正如官網中所描述的那樣:

Command bars can be placed at the top of the app window, at the bottom of the app window, and inline.

方法二:更改布局,使得頂部空間不足以展開 CommandBar

CommandBar 的 ClosedDisplayMode 設為 Compact 時,折疊狀態高度 48,展開狀態高度 60;在設為 Minimal 時,折疊狀態高度 24,展開狀態依然是 60。

這種模式下的展開和折疊高度

▲ 各種模式下的展開和折疊高度

鑒於 CommandBar 僅在空間不足時才會從向上展開變為向下展開,所以我們可以利用頂部空間的距離差來完成方向的修改。

對於 Compact 模式,我們僅能在上方預留不足 12 的尺寸,而對於 Minimal 模式,我們則有不大於 36 的尺寸可以預留。

在我們一開始的例子中,我們需要留出標題欄的高度,而標題欄高度為 32,所以使用 Minimal 模式時,我們的展開方向自然因為頂部空間不足而向下展開。另外,12 像素除了留白以外也沒什么作用,所以實質上 Compact 模式並不能通過這種方式解決展開方向的問題。

在使用 Minimal 的關閉模式時,可以向下展開
▲ 在使用 Minimal 的關閉模式時,可以向下展開

如果你設置的 SecondaryCommand 比較長,那么展開的時候也會占用較多的控件,於是也可以強制 CommandBar 向下展開。

方法三:設置 DefaultLabelPosition 避開展開方向的問題

如果不容易改展開方向,那么不讓 CommandBar 面臨展開方向的問題也是一個不錯的解決方案 —— 為 CommandBar 設置 DefaultLabelPosition 便是這樣的方案。

DefaultLabelPosition 屬性設置為 Right 或者 Collapsed 而不是 Bottom,那么 CommandBar 便不再需要展開這些按鈕了,因為即便展開也不會顯示更多的信息了,除了那個根本不會影響高度的更多項。

設置為 Collapsed 或者 Right 的 DefaultLabelPosition
▲ 設置為 Collapsed 或者 Right 的 DefaultLabelPosition

方法四:修改 CommandBar 的模板

不得不說這真是一個令人難受的方法,因為定義 CommandBar 模板和樣式的代碼行數有 1400 行左右。但這也是目前依然使用 CommandBar 控件時最好的方案了。

編輯控件模板的副本
▲ 編輯控件模板的副本

現在,使用 Visual Studio 設計器來幫助我們獲得 CommandBar 的完整默認樣式定義,就像上圖那樣。於是,我們可以閱讀其代碼並修改展開方向了。

代碼很長,為了能夠迅速理解其結構,我將其最關鍵的大綱部分貼到下面:

<ControlTemplate x:Key="CommandBarTemplate1">
    <Grid>
        <VisualStateManager.VisualStateGroups>
            <VisualStateGroup x:Name="DisplayModeStates">
                <VisualStateGroup.Transitions>
                    <VisualState From="CompactClosed" To="CompactOpenUp" />
                    <VisualState From="CompactOpenUp" To="CompactClosed" />
                    <VisualState From="CompactClosed" To="CompactOpenDown" />
                    <VisualState From="CompactOpenDown" To="CompactClosed" />
                    <VisualState From="MinimalClosed" To="MinimalOpenUp" />
                    <VisualState From="MinimalOpenUp" To="MinimalClosed" />
                    <VisualState From="MinimalClosed" To="MinimalOpenDown" />
                    <VisualState From="MinimalOpenDown" To="MinimalClosed" />
                    <VisualState From="HiddenClosed" To="HiddenOpenUp" />
                    <VisualState From="HiddenOpenUp" To="HiddenClosed" />
                    <VisualState From="HiddenClosed" To="HiddenOpenDown" />
                    <VisualState From="HiddenOpenDown" To="HiddenClosed" />
                </VisualStateGroup.Transitions>
                <VisualState x:Name="CompactClosed" />
                <VisualState x:Name="CompactOpenUp" />
                <VisualState x:Name="CompactOpenDown" />
                <VisualState x:Name="MinimalClosed" />
                <VisualState x:Name="MinimalOpenUp" />
                <VisualState x:Name="MinimalOpenDown" />
                <VisualState x:Name="HiddenClosed" />
                <VisualState x:Name="HiddenOpenUp" />
                <VisualState x:Name="HiddenOpenDown" />
            </VisualStateGroup>
        </VisualStateManager.VisualStateGroups>
    </Grid>
</ControlTemplate>

可以看到,對於每一種 ClosedDisplayMode,都有三種狀態與之對應 —— Closed、Up 和 Down。當然,Up 就是向上展開時的狀態,Down 就是向下展開時的狀態。而 Closed、Up 和 Down 之間的狀態切換有四種 —— Closed 到 Up、Up 到 Closed、Closed 到 Down 以及 Down 到 Closed。

於是,我們要獲得任何時候都向下展開的能力,我們便需要將所有的 Up 狀態修改成 Down 的狀態。

現在,我們將 將 <VisualState From="CompactClosed" To="CompactOpenDown" /> 的代碼復制到 <VisualState From="CompactClosed" To="CompactOpenUp" /> 中,<VisualState From="CompactOpenDown" To="CompactClosed" /> 內部的代碼復制到 <VisualState From="CompactOpenUp" To="CompactClosed" /> 中,將 <VisualState x:Name="CompactOpenDown" /> 內的代碼復制到 <VisualState x:Name="CompactOpenUp" /> 中。

也就是說,我們將所有 CompactClosed 和 CompactDown 的狀態復制到了 CompactClosed 和 CompactUp 的狀態中。這樣,即便 CommandBar 判定為向上展開,實際上的動畫和交互也都是向下展開的了。

以下是這樣修改后的效果。

使用樣式更改的展開方向
▲ 使用樣式更改的展開方向

究竟應該如何修改 CommandBar 的展開方向

在多數情況下,我想我們並沒有特別強烈的需求一定要讓 CommandBar 在頂部依然有空間的情況下展開方向向下。

如果有,那通常也是中大型項目,這時 CommandBar 樣式和模板所占用的那 1400 行左右的代碼也就不顯得多了。

但對於小型個人項目而言,可以考慮修改應用程序的外觀設計來規避這么長的代碼。例如讓 CommandBar 始終顯示或隱藏文字,或者讓 CommandBar 默認為 Minimal 的狀態。

如果你對其他控件有小型樣式的修改需求,可以閱讀我的另一篇文章:UWP 輕量級樣式定義(Lightweight Styling)

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM