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" />
......
基本上我需要在我的 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" />
......