UWP 上的枢轴控件自定义

Pivot control customization on UWP

基本上我需要在我的 uwp 应用程序上自定义 pivot 控件,我使用 windows phone 8.1 中的 pivot 样式。最终看起来是这样的(黄色部分是pivot item的内容,我只是用颜色来区分header和content)

但是现在不符合原设计的要求。所以我在这里有两个问题:

1.How 是否限制用户在一个方向上轻弹枢轴?例如,用户只能从左向右轻弹控件,因为如果从右向左轻弹枢轴,黄色内容部分将向左移动并覆盖 header。黄色部分的内容将完全随着您的手指移动,并且另一个被覆盖的枢轴 header 将显示,因为黄色部分移开了,如您在图像上看到的那样。这就是我关心滑动方向的原因,因为如果向左滑动,黄色部分会在手势完成之前覆盖 header 的一部分(图像中没有显示)。

2.How 更改未选中的透视项的前景色header?现在你可以看到,在滑动的过程中,黄色的内容部分会移开,显示未选中的header。这看起来很奇怪,根本不是一个好的设计。未选中的header假定为透明或与页面背景颜色相同

样式代码如下:

<Style x:Key="PivotStyle1" TargetType="Pivot">
        <Setter Property="Margin" Value="0"/>
        <Setter Property="Padding" Value="0"/>
        <Setter Property="Foreground" Value="{ThemeResource PivotForegroundThemeBrush}"/>
        <Setter Property="Background" Value="Transparent"/>
        <Setter Property="ItemsPanel">
            <Setter.Value>
                <ItemsPanelTemplate>
                    <Grid/>
                </ItemsPanelTemplate>
            </Setter.Value>
        </Setter>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Pivot">
                    <Grid x:Name="RootElement" Background="{TemplateBinding Background}" HorizontalAlignment="{TemplateBinding HorizontalAlignment}" VerticalAlignment="{TemplateBinding VerticalAlignment}">
                        <Grid.RowDefinitions>
                            <RowDefinition Height="Auto"/>
                            <RowDefinition Height="*"/>
                        </Grid.RowDefinitions>
                        <VisualStateManager.VisualStateGroups>
                            <VisualStateGroup x:Name="Orientation">
                                <VisualState x:Name="Portrait">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="TitleContentControl">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource PivotPortraitThemePadding}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                                <VisualState x:Name="Landscape">
                                    <Storyboard>
                                        <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Margin" Storyboard.TargetName="TitleContentControl">
                                            <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource PivotLandscapeThemePadding}"/>
                                        </ObjectAnimationUsingKeyFrames>
                                    </Storyboard>
                                </VisualState>
                            </VisualStateGroup>
                        </VisualStateManager.VisualStateGroups>
                        <ContentControl x:Name="TitleContentControl" ContentTemplate="{TemplateBinding TitleTemplate}" Content="{TemplateBinding Title}" Style="{StaticResource PivotTitleContentControlStyle}"/>
                        <ScrollViewer x:Name="ScrollViewer" HorizontalSnapPointsAlignment="Center" HorizontalSnapPointsType="MandatorySingle" HorizontalScrollBarVisibility="Hidden" Margin="{TemplateBinding Padding}" Grid.Row="1" Template="{StaticResource ScrollViewerScrollBarlessTemplate}" VerticalSnapPointsType="None" VerticalScrollBarVisibility="Disabled" VerticalScrollMode="Disabled" VerticalContentAlignment="Stretch" ZoomMode="Disabled">
                            <PivotPanel x:Name="Panel" VerticalAlignment="Stretch">
                                <PivotHeaderPanel x:Name="Header">
                                    <PivotHeaderPanel.RenderTransform>
                                        <CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0"/>
                                    </PivotHeaderPanel.RenderTransform>
                                </PivotHeaderPanel>
                                <ItemsPresenter x:Name="PivotItemPresenter">
                                    <ItemsPresenter.RenderTransform>
                                        <TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0"/>
                                    </ItemsPresenter.RenderTransform>
                                </ItemsPresenter>
                            </PivotPanel>
                        </ScrollViewer>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

以及枢轴控件的 XAML 代码:

<Pivot Style="{StaticResource PivotStyle1}">
        <Pivot.HeaderTemplate>
            <DataTemplate>
                <Grid Height="auto">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="21*"/>
                        <RowDefinition Height="299*"/>
                    </Grid.RowDefinitions>
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="5*"/>
                        <ColumnDefinition Width="19*"/>
                    </Grid.ColumnDefinitions>


                    <TextBlock  Text="{Binding}"
                                Margin="14,50,9,-120"
                                Grid.Row="1"
                                HorizontalAlignment="Center"
                                FontSize="48"
                                FontFamily="ms-appx:NotoSansCJKsc-Black.otf#Noto Sans CJK SC"
                                TextWrapping="Wrap"
                                LineStackingStrategy="BlockLineHeight"
                                LineHeight="49" Width="48"
                                Height="auto"/>
                </Grid>
            </DataTemplate>
        </Pivot.HeaderTemplate>

        <PivotItem Header="评论" Margin="83,-47,0,0" Background="Yellow">
            <Grid>
                <ListView x:Name="listview" d:LayoutOverrides="TopPosition, BottomPosition" ItemTemplate="{StaticResource GroupTemplate}" ItemsSource="{Binding Groups}" Margin="10,0,0,0"/>
            </Grid>
        </PivotItem>
        <PivotItem Header="转发" Margin="93,-47,0,0" Background="Yellow">
            <Grid>
                <ListView x:Name="listview2" d:LayoutOverrides="TopPosition, BottomPosition" ItemTemplate="{StaticResource GroupTemplate}" ItemsSource="{Binding Groups}"/>
            </Grid>
        </PivotItem>
    </Pivot>

第一个问题,您自定义了Pivot控件的样式,您上面的手势在手机模拟器上可以正常使用,但在本地机器上不行。这是Pivot控件设计中关于ManipulationMode的问题。 Pivot 控件的Gesture是在它的style里面实现的,所以可以单向操作,但是我们需要找到style中的关键点。

您可以使用 Manipulation 来执行此操作。您可以像这样修改 Pivot 控件的样式:

<PivotPanel x:Name="Panel" VerticalAlignment="Stretch">
    <PivotHeaderPanel x:Name="Header" ManipulationMode="None">
        <PivotHeaderPanel.RenderTransform>
            <CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0" />
        </PivotHeaderPanel.RenderTransform>
    </PivotHeaderPanel>
    <ItemsPresenter x:Name="PivotItemPresenter" ManipulationMode="None">
        <ItemsPresenter.RenderTransform>
            <TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0" />
        </ItemsPresenter.RenderTransform>
    </ItemsPresenter>
</PivotPanel>

并像这样使用这个 Pivot 控件:

<Pivot Style="{StaticResource PivotStyle1}" x:Name="myPivot" ManipulationMode="TranslateX" ManipulationStarting="OnStarting" ManipulationCompleted="OnCompleted">
   ...
</Pivot>

后面的代码:

public double pointx1;

private void OnCompleted(object sender, ManipulationCompletedRoutedEventArgs e)
{
    var pointx2 = Window.Current.CoreWindow.PointerPosition.X;
    if (pointx2 > pointx1)
    {
        if (myPivot.SelectedIndex == 0)
            myPivot.SelectedIndex = 1;
        else
            myPivot.SelectedIndex = 0;
    }
    else
        return;
}

private void OnStarting(object sender, ManipulationStartingRoutedEventArgs e)
{
    pointx1 = Window.Current.CoreWindow.PointerPosition.X;
}

这里也有一个变通的方法来解决这个问题,考虑到[=17=的样式没有操作,你可以使用PointerPoint来实现你可以修改你的[=的样式17=] 像这样控制:

<PivotPanel x:Name="Panel" VerticalAlignment="Stretch" ManipulationMode="None">
    <PivotHeaderPanel x:Name="Header">
        <PivotHeaderPanel.RenderTransform>
            <CompositeTransform x:Name="HeaderTranslateTransform" TranslateX="0" />
        </PivotHeaderPanel.RenderTransform>
    </PivotHeaderPanel>
    <ItemsPresenter x:Name="PivotItemPresenter">
        <ItemsPresenter.RenderTransform>
            <TranslateTransform x:Name="ItemsPresenterTranslateTransform" X="0" />
        </ItemsPresenter.RenderTransform>
    </ItemsPresenter>
</PivotPanel>

并像这样使用这个 Pivot 控件:

<Pivot Style="{StaticResource PivotStyle1}" PointerReleased="OnPointerExited" PointerPressed="OnPointerPressed" x:Name="myPivot">
  ...
</Pivot>

后面的代码:

public PointerPoint pointer1;

private void OnPointerExited(object sender, PointerRoutedEventArgs e)
{
    var pointer2 = e.GetCurrentPoint(myPivot);
    var position1x = pointer1.Position.X;
    var position2x = pointer2.Position.X;
    if (position2x > position1x)
    {
        if (myPivot.SelectedIndex == 0)
            myPivot.SelectedIndex = 1;
        else
            myPivot.SelectedIndex = 0;
    }
    else
        return;
}

private void OnPointerPressed(object sender, PointerRoutedEventArgs e)
{
    pointer1 = e.GetCurrentPoint(myPivot);
}

对于你的第二个问题,正如@ganchito55 所说,你可以

更新:

如果你只是不想在操作时看到其他项的表头,你可以这样修改PivotHeaderItem

......
<Setter Property="FontWeight" Value="{ThemeResource PivotHeaderItemThemeFontWeight}" />
<Setter Property="CharacterSpacing" Value="{ThemeResource PivotHeaderItemCharacterSpacing}" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="Transparent" />
<Setter Property="Padding" Value="{ThemeResource PivotHeaderItemMargin}" />
<Setter Property="Height" Value="48" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="IsTabStop" Value="False" />

......