探索 SwiftUI:全屏覆盖的 DragGesture

使用 SwiftUI 时,您熟悉sheet(isPresented:onDismiss:content:)用于呈现视图的修饰符。这是一种以模态样式叠加显示内容的便捷方法,并且带有内置的滑动手势来关闭视图。

但是如果你想用 afullScreenCover(isPresented:onDismiss:content:)代替怎么办?不幸的是,它没有开箱即用的相同滑动关闭功能。通过一些解决方法,可以使用DragGesture!

拖动手势

您可以使用 来DragGesture计算滑动的起始位置和结束位置之间的差异,以便在全屏视图上向下滑动。如果滑动距离超过特定阈值(例如 150 点),则您可以通过编程方式忽略fullScreenCover.

以下是如何设置的简单示例:

<span style="color:#596172"><span style="background-color:#ffffff"><span style="background-color:#2d2d2d"><span style="color:#cccccc"><code class="language-swift"><span style="color:#cc99cd">struct</span> <span style="color:#f8c555">SampleView</span><span style="color:#cccccc">:</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#cc99cd">@State</span> <span style="color:#cc99cd">private</span> <span style="color:#cc99cd">var</span> showCoverView <span style="color:#67cdcc">=</span> <span style="color:#f08d49">false</span><span style="color:#cc99cd">var</span> body<span style="color:#cccccc">:</span> <span style="color:#cc99cd">some</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">Button</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"PRESENT"</span><span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span>showCoverView<span style="color:#cccccc">.</span><span style="color:#f08d49">toggle</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">.</span><span style="color:#f08d49">fullScreenCover</span><span style="color:#cccccc">(</span>isPresented<span style="color:#cccccc">:</span> $showCoverView<span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">CoverView</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">}</span>
<span style="color:#cccccc">}</span><span style="color:#cc99cd">struct</span> <span style="color:#f8c555">CoverView</span><span style="color:#cccccc">:</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#999999">/// Use @Environment(\.presentationMode) private var presentationMode for iOS 14 and below</span><span style="color:#cc99cd">@Environment</span><span style="color:#cccccc">(</span><span style="color:#cccccc">\</span><span style="color:#cccccc">.</span>dismiss<span style="color:#cccccc">)</span> <span style="color:#cc99cd">private</span> <span style="color:#cc99cd">var</span> dismiss<span style="color:#cc99cd">var</span> body<span style="color:#cccccc">:</span> <span style="color:#cc99cd">some</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">Button</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"DISMISS"</span><span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span><span style="color:#999999">/// Use presentationMode.wrappedValue.dismiss() for iOS 14 and below</span><span style="color:#f08d49">dismiss</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">.</span><span style="color:#f08d49">gesture</span><span style="color:#cccccc">(</span><span style="color:#f8c555">DragGesture</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">.</span>onEnded <span style="color:#cccccc">{</span> value <span style="color:#cc99cd">in</span><span style="color:#cc99cd">if</span> value<span style="color:#cccccc">.</span>location<span style="color:#cccccc">.</span>y <span style="color:#67cdcc">-</span> value<span style="color:#cccccc">.</span>startLocation<span style="color:#cccccc">.</span>y <span style="color:#67cdcc">></span> <span style="color:#f08d49">150</span> <span style="color:#cccccc">{</span><span style="color:#999999">/// Use presentationMode.wrappedValue.dismiss() for iOS 14 and below</span><span style="color:#f08d49">dismiss</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">}</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span>
<span style="color:#cccccc">}</span></code></span></span></span></span>

关键是应用在 中的手势修饰符CoverView。这会添加一个DragGesture跟踪用户滑动的功能。在onEnded闭包中,它检查滑动平移的高度是否超过 150 点。如果是这样,它会dismiss()调用关闭fullScreenCover.

Chroma 游戏的示例

仔细看看Chroma Game应用程序中的真实示例。

在 中HomeView,视图模型包含一个名为 的枚举GameModeDestination,用于确定要呈现的颜色模式 - RGB 或 HSB。修饰符fullScreenCover使用此枚举来决定要显示哪个视图。

<span style="color:#596172"><span style="background-color:#ffffff"><span style="background-color:#2d2d2d"><span style="color:#cccccc"><code class="language-swift"><span style="color:#cc99cd">struct</span> <span style="color:#f8c555">HomeView</span><span style="color:#cccccc">:</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#cc99cd">@EnvironmentObject</span> <span style="color:#cc99cd">var</span> viewModel<span style="color:#cccccc">:</span> <span style="color:#f8c555">HomeViewModel</span><span style="color:#cc99cd">var</span> body<span style="color:#cccccc">:</span> <span style="color:#cc99cd">some</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">VStack</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">Text</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"MAIN VIEW IMPLEMENTATION"</span><span style="color:#cccccc">)</span><span style="color:#999999">/// Stripped implementation of Home View  </span><span style="color:#f8c555">Button</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"PRESENT RGB"</span><span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span>viewModel<span style="color:#cccccc">.</span>gameDestination <span style="color:#67cdcc">=</span> <span style="color:#cccccc">.</span>rgb<span style="color:#cccccc">}</span><span style="color:#cccccc">}</span><span style="color:#cccccc">.</span><span style="color:#f08d49">fullScreenCover</span><span style="color:#cccccc">(</span>item<span style="color:#cccccc">:</span> $viewModel<span style="color:#cccccc">.</span>gameDestination<span style="color:#cccccc">,</span>onDismiss<span style="color:#cccccc">:</span> viewModel<span style="color:#cccccc">.</span>didDismiss<span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span> item <span style="color:#cc99cd">in</span><span style="color:#cc99cd">switch</span> item <span style="color:#cccccc">{</span><span style="color:#cc99cd">case</span> <span style="color:#cccccc">.</span>rgb<span style="color:#cccccc">:</span> <span style="color:#f8c555">RGBView</span><span style="color:#cccccc">(</span>viewModel<span style="color:#cccccc">:</span> viewModel<span style="color:#cccccc">.</span>new<span style="color:#cccccc">)</span><span style="color:#cc99cd">case</span> <span style="color:#cccccc">.</span>hsb<span style="color:#cccccc">:</span> <span style="color:#f8c555">HSBView</span><span style="color:#cccccc">(</span>viewModel<span style="color:#cccccc">:</span> viewModel<span style="color:#cccccc">.</span>new<span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">}</span><span style="color:#cccccc">}</span>
<span style="color:#cccccc">}</span></code></span></span></span></span>

呈现的视图(RGBView 或 HSBView)包装在ContainerView.这ContainerView会在顶部显示一个关闭按钮,类似于 Apple Music 应用中的当前播放屏幕。该按钮使用自定义DismissButton视图:

<span style="color:#596172"><span style="background-color:#ffffff"><span style="background-color:#2d2d2d"><span style="color:#cccccc"><code class="language-swift"><span style="color:#cc99cd">public</span> <span style="color:#cc99cd">struct</span> <span style="color:#f8c555">DismissButton</span><span style="color:#cccccc">:</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#cc99cd">var</span> action<span style="color:#cccccc">:</span> <span style="color:#cccccc">(</span><span style="color:#cccccc">)</span> <span style="color:#67cdcc">-></span> <span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cc99cd">public</span> <span style="color:#cc99cd">init</span><span style="color:#cccccc">(</span><span style="color:#cc99cd">_</span> action<span style="color:#cccccc">:</span> <span style="color:#cc99cd">@escaping</span> <span style="color:#cccccc">(</span><span style="color:#cccccc">)</span> <span style="color:#67cdcc">-></span> <span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span><span style="color:#cc99cd">self</span><span style="color:#cccccc">.</span>action <span style="color:#67cdcc">=</span> action<span style="color:#cccccc">}</span><span style="color:#cc99cd">public</span> <span style="color:#cc99cd">var</span> body<span style="color:#cccccc">:</span> <span style="color:#cc99cd">some</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">Button</span><span style="color:#cccccc">(</span>action<span style="color:#cccccc">:</span> action<span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">RoundedRectangle</span><span style="color:#cccccc">(</span>cornerRadius<span style="color:#cccccc">:</span> <span style="color:#f08d49">16</span><span style="color:#cccccc">)</span><span style="color:#cccccc">.</span><span style="color:#f08d49">fill</span><span style="color:#cccccc">(</span><span style="color:#f8c555">Color</span><span style="color:#cccccc">.</span>gray<span style="color:#cccccc">)</span><span style="color:#cccccc">.</span><span style="color:#f08d49">frame</span><span style="color:#cccccc">(</span>width<span style="color:#cccccc">:</span> <span style="color:#f08d49">50</span><span style="color:#cccccc">,</span> height<span style="color:#cccccc">:</span> <span style="color:#f08d49">5</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">}</span>
<span style="color:#cccccc">}</span></code></span></span></span></span>

ContainerView本身应用DragGesture来启用滑动关闭交互:

<span style="color:#596172"><span style="background-color:#ffffff"><span style="background-color:#2d2d2d"><span style="color:#cccccc"><code class="language-swift"><span style="color:#cc99cd">struct</span> <span style="color:#f8c555">ContainerView</span><span style="color:#cccccc">:</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#cc99cd">@Environment</span><span style="color:#cccccc">(</span><span style="color:#cccccc">\</span><span style="color:#cccccc">.</span>presentationMode<span style="color:#cccccc">)</span> <span style="color:#cc99cd">var</span> presentation<span style="color:#cc99cd">@ObservedObject</span> <span style="color:#cc99cd">var</span> viewModel<span style="color:#cccccc">:</span> <span style="color:#f8c555">MainViewModel</span><span style="color:#cc99cd">var</span> body<span style="color:#cccccc">:</span> <span style="color:#cc99cd">some</span> <span style="color:#f8c555">View</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">VStack</span> <span style="color:#cccccc">{</span><span style="color:#f8c555">DismissButton</span> <span style="color:#cccccc">{</span> <span style="color:#f08d49">dismiss</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span> <span style="color:#cccccc">}</span><span style="color:#f8c555">Text</span><span style="color:#cccccc">(</span><span style="color:#7ec699">"IMPLEMENTATION"</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">.</span><span style="color:#f08d49">gesture</span><span style="color:#cccccc">(</span><span style="color:#f8c555">DragGesture</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">.</span>onEnded <span style="color:#cccccc">{</span> value <span style="color:#cc99cd">in</span><span style="color:#cc99cd">if</span> value<span style="color:#cccccc">.</span>location<span style="color:#cccccc">.</span>y <span style="color:#67cdcc">-</span> value<span style="color:#cccccc">.</span>startLocation<span style="color:#cccccc">.</span>y <span style="color:#67cdcc">></span> <span style="color:#f08d49">150</span> <span style="color:#cccccc">{</span><span style="color:#f08d49">dismiss</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cccccc">}</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span><span style="color:#cc99cd">private</span> <span style="color:#cc99cd">func</span> <span style="color:#f08d49">dismiss</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span> <span style="color:#cccccc">{</span>viewModel<span style="color:#cccccc">.</span><span style="color:#f08d49">invalidateTimer</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span>viewModel<span style="color:#cccccc">.</span><span style="color:#f08d49">dismiss</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span>presentation<span style="color:#cccccc">.</span>wrappedValue<span style="color:#cccccc">.</span><span style="color:#f08d49">dismiss</span><span style="color:#cccccc">(</span><span style="color:#cccccc">)</span><span style="color:#cccccc">}</span>
<span style="color:#cccccc">}</span></code></span></span></span></span>

当用户向下滑动ContainerView并且滑动距离超过150点时,dismiss()调用该函数。此函数更新视图模型,使任何活动计时器无效,然后使用presentationMode环境变量关闭视图。

结论

这就是全部!只需几行代码,您就可以调整体验fullScreenCover以支持许多用户期望从模式视图中获得的滑动关闭交互类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/11342.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

APScheduler定时器使用【重写SQLAlchemyJobStore版】:django中使用apscheduler,使用mysql做存储后端

一、环境配置 python3.8.10 包&#xff1a; APScheduler3.10.4 Django3.2.7 djangorestframework3.15.1 SQLAlchemy2.0.29 PyMySQL1.1.0 项目目录情况 gs_scheduler 应用 commands &#xff1a; 主要用来自定义命令&#xff0c;python manage.py crontab schedulers&#…

OpenHarmony开发案例【大合集】

OpenHarmony Codelabs 概要简介 为帮助开发者快速熟悉OpenHarmony的能力以及相关的应用开发流程&#xff0c;我们提供了一系列的基于趣味场景的应用示例&#xff0c;即Codelabs&#xff0c;开发者可以根据我们的文档一步步的学习和完成简单项目的开发。 目录 优秀案例 一次开…

小米/红米手机刷机错误:Missmatching image and device

报错&#xff1a; Missmatching image and device。 场景&#xff1a; 该解决方法只适用于手机是通过EMT解锁的。 解决方法&#xff1a; 打开刷机脚本&#xff0c;并注释检测脚本&#xff1a; 刷机脚本根据不同的刷机方式&#xff0c;选择编辑不同的脚本&#xff0c;例如&am…

nginx关于并发的总结

一、环境 1.nginx版本 [rootnode4 ~]# nginx -V nginx version: nginx/1.18.0 built by gcc 4.8.5 20150623 (Red Hat 4.8.5-44) (GCC) configure arguments: --prefix/usr/local/nginx2.操作系统 centos73.硬件配置 [rootnode2 ~]# cat /proc/cpuinfo |grep process proc…

2024年最顶尖的AI驱动SEO工具|TodayAI

在当今数字营销的竞争环境中&#xff0c;获得搜索引擎的高排名至关重要&#xff0c;因为它直接关联到网站的有机流量和品牌的在线影响力。搜索引擎优化&#xff08;SEO&#xff09;是提高网站排名的关键方式&#xff0c;通过优化网站内容和结构来符合搜索引擎的算法要求。然而&…

win server服务器 关闭危险端口 135,137,138,139,445的方法

通过防火墙来控制 打开控制面板 选择检查防火墙状态 选择高级设置 选择入站规则&#xff0c;再新建规则 选择端口&#xff0c;下一步 选择端口应用于啥协议&#xff0c;再指定端口&#xff0c;再下一步 选择阻止连接&#xff0c;下一步 下一步 给规则别名一下&#xff0c;方便…

5.12学习总结

一.JAVA聊天室项目 文件发送 使用 Java Socket 实现聊天内容或文件的传输的原理如下&#xff1a; 服务器端启动&#xff1a;聊天室的服务器端在指定的端口上监听客户端的连接。它创建一个 ServerSocket 对象&#xff0c;并通过调用 accept() 方法等待客户端的连接请求。客户…

快速入门:利用Go语言下载Amazon商品信息的步骤详解

概述 在这篇文章中&#xff0c;我们将深入探讨如何利用Go语言这一强大的工具&#xff0c;结合代理IP技术和多线程技术&#xff0c;实现高效下载Amazon的商品信息。首先&#xff0c;让我们来看看为什么选择Go语言作为开发网络爬虫的首选语言。 Go语言在网络开发中的特点 简洁…

grep 整理

grep 整理 1. 正则表达式和通配符2. grep2.1 基本用法2.2 进阶使用2.3 配合正则表达式使用2.4 grep增强版 1. 正则表达式和通配符 首先&#xff0c;我们回顾下正则表达式和通配符相关内容&#xff0c;这有助于接下来的grep学习&#xff1a; 基础正则表达式 RE 字符意义与范例…

项目经理根本不需要考PMP证书,浪费?

我首先会考虑你是否有这方面的需求&#xff0c;这是肯定的。如果你只是为了跟风而考证&#xff0c;因为别人都在考&#xff0c;所以你也跟着考&#xff0c;这样做是毫无意义的。 那么如何判断自己是否有这方面的需求呢&#xff1f; 1、工作 在工作中要考虑三个条件&#xff…

内裤什么牌子的质量好男士?2024男士内裤排行榜出炉

换新内裤这件事情对很难男生来说都挺难的&#xff0c;因为现在的男士内裤品牌比较多&#xff0c;而且还有各种不同材质的区分。尤其是大多数男士对自己穿的内裤都不是特别在意&#xff0c;实际上如果长期不更换内裤&#xff0c;会使内裤的舒适性、透气性降低&#xff0c;而且还…

附录2 创建flask镜像

目录 1 python镜像 2 安装flask 3 把项目文件扔进去 3.1 创建git仓库 3.2 上传文件 3.3 获取git链接 3.4 在容器中git clone 4 启动flask服务 5 将容器保存为镜像 6 映射端口运行镜像 7 遇到的问题 8 Dockerfile创建镜像 1 python镜像 首先找一下fla…

【全开源】keep健身小程序基于FastAdmin+ThinkPHP+UniApp

基于FastAdminUniApp&#xff08;目前仅支持微信小程序&#xff09;开发的健身相关行业小程序&#xff0c;程序适用于健身房、瑜伽馆、游泳馆、篮球馆等健身培训场所。平台拥有课程售卖、课程预约、多门店管理、私教预约、教练端、会员卡办理、在线商城、分销模块、页面自定义装…

Charles客户端下载

1.Charles客户端下载&#xff1a; 官网地址&#xff1a;Download a Free Trial of Charles • Charles Web Debugging Proxy 2.下载安装完成后激活 激活网站地址&#xff1a;https://www.zzzmode.com/mytools/charles/ 3.help&#xff0c;选择第一个&#xff0c;激活

Docker基础复习

文章目录 基础Docker基础命令镜像操作命令容器操作命令 案例:安装MySql案例:查看DockerHub&#xff0c;拉取Nginx镜像&#xff0c;并运行容器Docker命令起别名 基础 Docker基础命令 启动Docker systemctl start docker镜像操作命令 从远程仓具下载镜像到本地 docker pull 镜像…

Linux开发--Linux字符设备驱动设计

Linux字符设备驱动设计 概述 驱动的定义与功能 计算机系统中存在着大量的设备&#xff0c; 操作系统要求能够控制和管理这些硬件&#xff0c; 而驱动就是帮助操作系统完成这个任务。 驱动相当于硬件的接口&#xff0c; 它直接操作、 控制着我们的硬件&#xff0c; 操作系统通…

五款商用加密软件推荐 | 商用加密软件排行榜

没有网络安全就没有国家安全。信息安全是国家经济社会稳定运行&#xff0c;广大人民群众利益的保障。 对于公司来讲&#xff0c;数据安全同样是企业可持续发展的重要保障&#xff0c;防止内部核心数据、知识产权的泄露是企业数据安全的重要工作。下面是五款企业常用的加密软件…

网络安全学习路线+自学笔记(超详细) 自学网络安全看这一篇就够了

一、什么是网络安全 网络安全是一种综合性的概念&#xff0c;涵盖了保护计算机系统、网络基础设施和数据免受未经授权的访问、攻击、损害或盗窃的一系列措施和技术。经常听到的 “红队”、“渗透测试” 等就是研究攻击技术&#xff0c;而“蓝队”、“安全运营”、“安全运维”…

正点原子[第二期]Linux之ARM(MX6U)裸机篇学习笔记-15.1,2,3-GPIO中断控制实验

前言&#xff1a; 本文是根据哔哩哔哩网站上“正点原子[第二期]Linux之ARM&#xff08;MX6U&#xff09;裸机篇”视频的学习笔记&#xff0c;在这里会记录下正点原子 I.MX6ULL 开发板的配套视频教程所作的实验和学习笔记内容。本文大量引用了正点原子教学视频和链接中的内容。…

C--贪吃蛇

前言 贪吃蛇游戏是一个耳熟能详的小游戏,本次我们讲解他的简单的实现,需要掌握基本的API知识(http://t.csdnimg.cn/uHH6y),简单的C语言知识和基本的数据结构链表 简单的准备工作 蛇的节点 在游戏运⾏的过程中&#xff0c;蛇每次吃⼀个⻝物&#xff0c;蛇的⾝体就会变⻓⼀节&a…