web-dev-qa-db-ja.com

スワイプジェスチャーを追加してSplitViewペインを開く

UWPのSplitViewコントロール(別名 "ハンバーガーメニュー")にスワイプジェスチャーを追加しようとしています。これは、ピボットコントロールの左/右へのスワイプに似ています。ジェスチャーを設定してその表示モードを変更するにはどうすればよいですか?

IOS 8以降では、UISplitViewControllerを使用してpresentsWithGestureプロパティを設定できますが、WinRTには同様の機能はありません。

今このブログを読んだ後: http://blogs.msdn.com/b/cdndevs/archive/2015/07/10/uwp-new-controls-part-2-splitview.aspx 、I SplitViewコントロールにはDisplayModeプロパティがあり、その状態を変更するにはVisualStateManagerを使用する必要があることを認識しました。これがvsmで実現可能であることは知りません。

任意のヘルプ/ヒントをいただければ幸いです。

21
iou90

興味深い質問です! :)

最近、SwipeableSplitViewコントロールを拡張するSplitViewを作成して、DisplayModeOverlayに設定されているときに、左端からのスワイプジェスチャーを有効にしますモード、ただし必要に応じて自由に拡張してください)。

私がしているのは、コントロールのスタイル内で、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プロパティを使用する場合は、代わりにIsSwipeablePaneOpenを使用してください。

これは、GitHubで作成したデモアプリでの動作です。あなたは完全なソースコードを見つけることができます ここ

enter image description here


クレジット

  • SplitViewテンプレートは、Koen Zwikstraのすばらしい Visual Studio UWPテンプレートから生成されました
  • ページのアニメーションと他のいくつかの実装は、Jerry Nixonの this post に触発されました。
39
Justin XL

まあ、そのブログではレスポンシブUIを作成するためにvsmが使用されています。 SplitViewでスワイプジェスチャーを追加するには、次のようにします。

  • SplitViewのコンテンツのルートパネルでジェスチャーを検出し、それに含まれるManipulatioinイベントハンドラーを追加します。
  • ManipulationイベントでSplitViewのIsPaneOpenプロパティを処理します。
1
JuniperPhoton