添加滑动手势以打开SplitView窗格

时间:2015-08-20 01:55:02

标签: c# windows-runtime winrt-xaml windows-10 uwp

我正在尝试向UWP的SplitView控件(又名" hamburger菜单")添加滑动手势,类似于Pivot控件的左/右滑动。如何设置手势以更改其显示模式?

在iOS 8及更高版本中,我可以使用UISplitViewController并设置presentsWithGesture属性来执行此操作,但WinRT中没有类似的东西。

现在看完这个博客:http://blogs.msdn.com/b/cdndevs/archive/2015/07/10/uwp-new-controls-part-2-splitview.aspx后,我意识到SplitView控件中有DisplayMode属性,我应该使用VisualStateManager来改变它的状态但是我怎样才能使用vsm来平移左边的窗格出来吗?我不知道这可以通过vsm实现。

非常感谢任何帮助/提示。

2 个答案:

答案 0 :(得分:39)

有趣的问题! :)

我最近创建了一个SwipeableSplitView扩展SplitView控件,以便在DisplayMode设置为{{1}时启用从左边缘手势滑动(因为我没有看到在其他模式中使用它的意义,但随时可以随意扩展它。)

我正在做的就是在控件的样式中,在Overlay图层的顶部创建另一个图层并处理那里的所有手势。

PaneRoot

在更新新图层变换对象的<Grid x:Name="PaneRoot" ManipulationMode="TranslateX" Grid.ColumnSpan="2" HorizontalAlignment="Left" Background="{TemplateBinding PaneBackground}" Width="{Binding TemplateSettings.OpenPaneLength, RelativeSource={RelativeSource Mode=TemplatedParent}}"> <Grid.Clip> <RectangleGeometry x:Name="PaneClipRectangle"> <RectangleGeometry.Transform> <CompositeTransform x:Name="PaneClipRectangleTransform" /> </RectangleGeometry.Transform> </RectangleGeometry> </Grid.Clip> <Grid.RenderTransform> <CompositeTransform x:Name="PaneTransform" TranslateX="{Binding RenderTransform.TranslateX, ElementName=PanArea}" /> </Grid.RenderTransform> <Border Child="{TemplateBinding Pane}" /> <Rectangle x:Name="HCPaneBorder" Fill="{ThemeResource SystemControlForegroundTransparentBrush}" HorizontalAlignment="Right" Visibility="Collapsed" Width="1" x:DeferLoadStrategy="Lazy" /> </Grid> <!--a new layer here to handle all the gestures --> <Grid x:Name="OverlayRoot" Grid.ColumnSpan="2"> <Grid.ColumnDefinitions> <ColumnDefinition Width="{Binding TemplateSettings.OpenPaneGridLength, RelativeSource={RelativeSource Mode=TemplatedParent}}" /> <ColumnDefinition Width="Auto" /> <ColumnDefinition /> </Grid.ColumnDefinitions> <!--the actual element for panning, manipulations happen here--> <Rectangle x:Name="PanArea" Fill="Transparent" ManipulationMode="TranslateX" Width="{Binding PanAreaThreshold, RelativeSource={RelativeSource Mode=TemplatedParent}}" Grid.Column="1"> <Rectangle.RenderTransform> <CompositeTransform TranslateX="{Binding PanAreaInitialTranslateX, RelativeSource={RelativeSource Mode=TemplatedParent}}" /> </Rectangle.RenderTransform> </Rectangle> <!--this is used to dismiss this swipeable pane--> <Rectangle x:Name="DismissLayer" Fill="Transparent" Grid.Column="2" /> </Grid> 时,我还会更新TranslateX以保持其位置同步。

PaneRoot

请记住,因为void OnManipulationStarted(object sender, ManipulationStartedRoutedEventArgs e) { _panAreaTransform = PanArea.RenderTransform as CompositeTransform; _paneRootTransform = PaneRoot.RenderTransform as CompositeTransform; if (_panAreaTransform == null || _paneRootTransform == null) { throw new ArgumentException("Make sure you have copied the default style to Generic.xaml!!"); } } void OnManipulationDelta(object sender, ManipulationDeltaRoutedEventArgs e) { var x = _panAreaTransform.TranslateX + e.Delta.Translation.X; // keep the pan within the bountry if (x < PanAreaInitialTranslateX || x > 0) return; // while we are panning the PanArea on X axis, let's sync the PaneRoot's position X too _paneRootTransform.TranslateX = _panAreaTransform.TranslateX = x; } void OnManipulationCompleted(object sender, ManipulationCompletedRoutedEventArgs e) { var x = e.Velocities.Linear.X; // ignore a little bit velocity (+/-0.1) if (x <= -0.1) { CloseSwipeablePane(); } else if (x > -0.1 && x < 0.1) { if (Math.Abs(_panAreaTransform.TranslateX) > Math.Abs(PanAreaInitialTranslateX) / 2) { CloseSwipeablePane(); } else { OpenSwipeablePane(); } } else { OpenSwipeablePane(); } } 属性不是虚拟的,我必须创建另一个IsPaneOpen来包装前者。因此,无论何时使用IsSwipeablePaneOpen属性,请改用IsPaneOpen

这是我在GitHub中创建的演示应用程序中的工作原理。您可以找到完整的源代码here

enter image description here

<强>积分

答案 1 :(得分:1)

嗯,vsm用于在该博客中制作响应式用户界面。要在SplitView中添加滑动手势,这就是我所做的:

  • 在SplitView的内容的根面板上检测手势,并添加一些Manipulatioin涉及的事件处理程序。
  • 在Manipulation事件中处理SplitView的IsPaneOpen属性。