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啦。

 

posted on 2018-03-25 00:26  叫我蓝火火  阅读(698)  评论(1编辑  收藏  举报

导航