1. 程式人生 > >UWP:可滾動的PivotHeader

UWP:可滾動的PivotHeader

style屬性 設計器 bject 也不會 horizon fse 左右 lB ima

原文:UWP:可滾動的PivotHeader

UWP開發裏,Pivot真是個令人又愛又恨的控件。為了實現某些可滾動Header的效果,有些大佬甚至去掉了原本的Header,使用一個ListView或者ListBox自己畫Header,不過這樣會讓控件變得很復雜。

既然Pivot是一個模板化控件,那麽應該有方法直接讓Header可以滾動。

先貼效果圖:

技術分享圖片

先自定義Pivot的Style,從generic.xaml找(位置應該在C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\(你的SDK版本)\Generic),或者在xaml設計器裏右鍵,編輯Style也可以。

找到Style中的<VisualStateGroup x:Name="NavigationButtonsVisibility">,到</VisualStateGroup>,包括這兩行,全部註釋掉,就可以取消左右兩側的按鈕。

分析一下,Pivot有兩個狀態:

當HeaderPanel寬度小於Pivot寬度的時候,也就是Headers不溢出的時候,Header的位置是固定的;

當HeaderPanel寬度大於Pivot寬度的時候,也就是Headers溢出的時候,被選中的Header會被移動到第一位。

觀察一下Style可以得知,這個是HeaderStates這個VisualStateGroup控制的,所以和上面一樣,註釋掉HeaderStates這個VisualStateGroup,這樣就取消了動態Header和固定Header的狀態轉換。

然後往下找,找到<PivotHeaderPanel x:Name="Header" >到</PivotHeaderPanel>,全部註釋掉,這是動態的Header,我們只需要靜態的。

然後把<PivotHeaderPanel x:Name="StaticHeader">的Visibility改成Visible,這樣就默認使用靜態的Header,即使Headers溢出也不會自己移動。

最後,在PivotHeaderPanel外面的Grid外面套一層ScrollViewer,代碼會變成下面的樣子:

<ScrollViewer ScrollViewer.HorizontalScrollBarVisibility
="Hidden" ScrollViewer.HorizontalScrollMode="Enabled" ScrollViewer.VerticalScrollBarVisibility="Disabled" ScrollViewer.VerticalScrollMode="Disabled" > <Grid Background="{ThemeResource PivotHeaderBackground}"> <Grid.RenderTransform> <CompositeTransform x:Name="HeaderOffsetTranslateTransform" /> </Grid.RenderTransform> <PivotHeaderPanel x:Name="StaticHeader" Visibility="Visible" > <PivotHeaderPanel.RenderTransform> <CompositeTransform x:Name="StaticHeaderTranslateTransform"/> </PivotHeaderPanel.RenderTransform> </PivotHeaderPanel> <!--<PivotHeaderPanel x:Name="Header" > <PivotHeaderPanel.RenderTransform> <CompositeTransform x:Name="HeaderTranslateTransform"/> </PivotHeaderPanel.RenderTransform> </PivotHeaderPanel>--> </Grid> </ScrollViewer>

運行一下試試看,Header是不是可以使用鼠標滾輪左右滾動了。

至此,本文就已經可以結束了。不過有人可能會問,為什麽你的Pivot會有下面的Focus,我的就沒有呢?請接著往下看:

從xaml設計器貼出來的Pivot的Style裏,並沒有Header相關的,Selected、Unselected之類的VisualState,是微軟忘了寫?其實並不是。

如果你和ItemsControl經常打交道,你會發現ListView、GridView之類的控件都有個ItemContainerStyle屬性,控制Items的容器的Style,一般來說Select之類的VisualState都在這裏面,可是Pivot並沒有提供Header的ItemContainerStyle啊?

其實PivotHeaderItemContainerStyle也是有的,只是微軟沒有直接提供給我們,需要手動從文件裏復制一下,並且用一些非常規的方式使其生效。

首先打開generic.xaml,,在裏面全局搜索PivotHeaderItem,可以找到如下段落:

技術分享圖片

將這一段復制出來,這時你有三個選擇:

  1. 如果你自定義了Pivot的Style,請將這段放在<ControlTemplate TargetType="Pivot"> <Grid x:Name="RootElement" ...><Grid.Resource>(放在這裏)</Grid.Resource>。
  2. 如果沒有自定義Style,請將這段放在<Pivot><Pivot.Resource>(放在這裏)</Pivot.Resource>
  3. 單獨寫在資源字典或者Page.Resource或者Application.Resource裏,把x:Key設置為PivotHeaderItemContainerStyle,然後在如上兩個位置寫<Style TargetType="PivotHeaderItem" BaseOn="{StaticResource PivotHeaderItemContainerStyle}">

註意:對於最終生效的Style(1、2和3中帶BaseOn的Style),不要設置x:Key和x:Name!(不設置x:Key和x:Name的Style資源,會應用給他的所有TargetType匹配的子控件。)

這樣我們就可以自定義PivotHeaderItemContainerStyle了。

然後找到<VisualStateGroup x:Name="SelectionStates">,在裏面的Selected,SelectedPointerOver,SelectedPressed的Storyboard中加入如下的段落:

<ObjectAnimationUsingKeyFrames Storyboard.TargetName="FocusPipe" Storyboard.TargetProperty="Visibility">
    <DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
</ObjectAnimationUsingKeyFrames>

這樣再運行,就可以在Header被選中的時候顯示下面的Focus啦。

UWP:可滾動的PivotHeader