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

2024-02-02

我正在尝试向 UWP 的 SplitView 控件(又名“汉堡菜单”)添加滑动手势,类似于 Pivot 控件的左/右滑动。如何设置手势来改变它的显示模式?

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

现在读完这篇博客后:http://blogs.msdn.com/b/cdndevs/archive/2015/07/10/uwp-new-controls-part-2-splitview.aspx http://blogs.msdn.com/b/cdndevs/archive/2015/07/10/uwp-new-controls-part-2-splitview.aspx,我意识到 SplitView 控件中有 DisplayMode 属性,我应该使用 VisualStateManager 来更改它的状态但是如何使用 vsm 来平移左窗格呢?我不知道 vsm 可以实现这一点。

任何帮助/提示将不胜感激。


有趣的问题! :)

我最近创建了一个SwipeableSplitView这扩展了SplitView控制以启用从左边缘滑动手势时DisplayMode被设定为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财产、使用IsSwipeablePaneOpen反而。

这就是我在 GitHub 中创建的演示应用程序的工作原理。你可以找到完整的源代码here https://github.com/JustinXinLiu/SwipeableSplitView.


Credits

  • SplitView 模板是从 Koen Zwikstra 的很棒的模板生成的Visual Studio UWP 模板 https://visualstudiogallery.msdn.microsoft.com/b3eb9b90-cc39-4b5c-bf94-497cba6e4f6f.
  • 页面动画和其他一些实现的灵感来自这个帖子 http://blog.jerrynixon.com/2015/04/implementing-hamburger-button-with.html来自杰里·尼克松。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

添加滑动手势以打开 SplitView 窗格 的相关文章

  • 没有强命名的代码签名是否会让您的应用程序容易被滥用?

    尝试了解authenticode代码签名和强命名 我是否正确地认为 如果我对引用一些 dll 非强命名 的 exe 进行代码签名 恶意用户就可以替换我的 DLL 并以看似由我签名但正在运行的方式分发应用程序他们的代码 假设这是真的 那么您似
  • 通过 CMIS (dotCMIS) 连接到 SP2010:异常未经授权

    我正在使用 dotCMIS 并且想要简单连接到我的 SP2010 服务器 我尝试用 C 来做到这一点 如下所示http chemistry apache org dotnet getting started with dotcmis htm
  • WCF RIA 服务 - 加载多个实体

    我正在寻找一种模式来解决以下问题 我认为这很常见 我正在使用 WCF RIA 服务在初始加载时将多个实体返回给客户端 我希望两个实体异步加载 以免锁定 UI 并且我想利用 RIA 服务来执行此操作 我的解决方案如下 似乎有效 这种方法会遇到
  • GLKit的GLKMatrix“列专业”如何?

    前提A 当谈论线性存储器中的 列主 矩阵时 列被一个接一个地指定 使得存储器中的前 4 个条目对应于矩阵中的第一列 另一方面 行主 矩阵被理解为依次指定行 以便内存中的前 4 个条目指定矩阵的第一行 A GLKMatrix4看起来像这样 u
  • 动态加载程序集的应用程序配置

    我正在尝试将模块动态加载到我的应用程序中 但我想为每个模块指定单独的 app config 文件 假设我的主应用程序有以下 app config 设置
  • 不支持将数据直接绑定到存储查询(DbSet、DbQuery、DbSqlQuery)

    正在编码视觉工作室2012并使用实体模型作为我的数据层 但是 当页面尝试加载时 上面提到的标题 我使用 Linq 语句的下拉控件往往会引发未处理的异常 下面是我的代码 using AdventureWorksEntities dw new
  • 使用实体框架模型输入安全密钥

    这是我今天的完美想法 Entity Framework 中的强类型 ID 动机 比较 ModelTypeA ID 和 ModelTypeB ID 总是 至少几乎 错误 为什么编译时不处理它 如果您使用每个请求示例 DbContext 那么很
  • 类模板参数推导 - clang 和 gcc 不同

    下面的代码使用 gcc 编译 但不使用 clang 编译 https godbolt org z ttqGuL template
  • 用于登录 .NET 的堆栈跟踪

    我编写了一个 logger exceptionfactory 模块 它使用 System Diagnostics StackTrace 从调用方法及其声明类型中获取属性 但我注意到 如果我在 Visual Studio 之外以发布模式运行代
  • 堆栈溢出:堆栈空间中重复的临时分配?

    struct MemBlock char mem 1024 MemBlock operator const MemBlock b const return MemBlock global void foo int step 0 if ste
  • 在 ASP.NET 5 中使用 DI 调用构造函数时解决依赖关系

    Web 上似乎充斥着如何在 ASP NET 5 中使用 DI 的示例 但没有一个示例显示如何调用构造函数并解决依赖关系 以下只是众多案例之一 http social technet microsoft com wiki contents a
  • C# 中通过 Process.Kill() 终止的进程的退出代码

    如果在我的 C 应用程序中 我正在创建一个可以正常终止或开始行为异常的子进程 在这种情况下 我通过调用 Process Kill 来终止它 但是 我想知道该进程是否已退出通常情况下 我知道我可以获得终止进程的错误代码 但是正常的退出代码是什
  • 重载<<的返回值

    include
  • 显示UnityWebRequest的进度

    我正在尝试使用下载 assetbundle统一网络请求 https docs unity3d com ScriptReference Networking UnityWebRequest GetAssetBundle html并显示进度 根
  • 如何设计以 char* 指针作为类成员变量的类?

    首先我想介绍一下我的情况 我写了一些类 将 char 指针作为私有类成员 而且这个项目有 GUI 所以当单击按钮时 某些函数可能会执行多次 这些类是设计的单班在项目中 但是其中的某些函数可以执行多次 然后我发现我的项目存在内存泄漏 所以我想
  • while 循环中的 scanf

    在这段代码中 scanf只工作一次 我究竟做错了什么 include
  • 向现有 TCP 和 UDP 代码添加 SSL 支持?

    这是我的问题 现在我有一个 Linux 服务器应用程序 使用 C gcc 编写 它与 Windows C 客户端应用程序 Visual Studio 9 Qt 4 5 进行通信 是什么very在不完全破坏现有协议的情况下向双方添加 SSL
  • 基于 OpenCV 边缘的物体检测 C++

    我有一个应用程序 我必须检测场景中某些项目的存在 这些项目可以旋转并稍微缩放 更大或更小 我尝试过使用关键点检测器 但它们不够快且不够准确 因此 我决定首先使用 Canny 或更快的边缘检测算法 检测模板和搜索区域中的边缘 然后匹配边缘以查
  • 是否可以在 .NET Core 中将 gRPC 与 HTTP/1.1 结合使用?

    我有两个网络服务 gRPC 客户端和 gRPC 服务器 服务器是用 NET Core编写的 然而 客户端是托管在 IIS 8 5 上的 NET Framework 4 7 2 Web 应用程序 所以它只支持HTTP 1 1 https le
  • 如何在文本框中插入图像

    有没有办法在文本框中插入图像 我正在开发一个聊天应用程序 我想用图标图像更改值 等 但我找不到如何在文本框中插入图像 Thanks 如果您使用 RichTextBox 进行聊天 请查看Paste http msdn microsoft co

随机推荐