SwiftUI魔法:通过DragGesture互动提升用户体验

本教程会用 DragGesture 再打造一个我们经常在 app 中见到的交互动画效果,这个效果很有利于提升用户交互体验,相信你在很多 app 中见过这个交互,我们来一起看看具体实现吧

本章节的例子是一个可以上下拖动的登录页面,页面搭建很简单我们就不细讲了,我把代码贴在下面

初始状态

css 复制代码
struct DragGestureSample2: View {
    var body: some View {
        ZStack {
            Color.green
                .ignoresSafeArea()
            
            SignupView()
        }
        .ignoresSafeArea(edges: .bottom)
    }
}
css 复制代码
struct SignupView: View {
    var body: some View {
        VStack(spacing: 30) {
            Image(systemName: "chevron.up")
                .padding(.top)
            
            Text("Sign up")
                .font(.headline)
                .fontWeight(.semibold)
            
            Image(systemName: "flame.fill")
                .resizable()
                .scaledToFit()
                .frame(width: 120, height: 120)
            
            Text("这是我最喜欢的SwiftUI教程,我推荐给所有的的盆友们关注,点赞。也可以关注公众号,每天都会更新新知识哟,公众号:RobotPBQ")
                .multilineTextAlignment(.center)
            
            Text("Create an Account".uppercased())
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .padding(.horizontal)
                .background(Color.black.cornerRadius(10))
            
            Spacer()
        }
        .frame(maxWidth: .infinity)
        .background(Color.white)
        .cornerRadius(30)
    }
}

效果如下:

下面我们来开始今天的主题内容。

把页面放置在View的底部

我们把这个登录的页面往下移动到只留出头部的箭头和登录的字样。

可以创建一个 startingOffsetY 变量,用于保存起始值 ,使用 startingOffsetY 来把页面移动到底部。

less 复制代码
@State var startingOffsetY: CGFloat = UIScreen.main.bounds.height * 0.85

SignupView()
  .offset(y: startingOffsetY)

移动目标视图

当我们使用 DragGesture 手势拖动页面底部的白色区域时,页面会随着我们的手势来进行页面的上下位移

我们用一个变量来保存当前位移的距离

swift 复制代码
@State var currentDragOffsetY: CGFloat = 0

在 SignupView 的下面再补充一个Offset

scss 复制代码
SignupView()
                .offset(y: startingOffsetY)
 .offset(y: currentDragOffsetY) 
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            withAnimation(.spring()) {
 currentDragOffsetY = value.translation.height
                            }
                        }

此时我们已经可以移动 SignupView 视图了。但是你会发现你在拖动的过程中,视图一不小心就不见了。

原因是因为没有处理 onEnded 事件。我们来处理一下

处理结束事件

我们需要再创建一个结束为值的 endingOffsetY 变量。

less 复制代码
 @State var endingOffsetY: CGFloat = 0

SignupView()
                .offset(y: startingOffsetY)
                .offset(y: currentDragOffsetY)
 .offset(y: endingOffsetY)
                .gesture(
                    DragGesture()
                        .onChanged { value in
                            withAnimation(.spring()) {
                                currentDragOffsetY = value.translation.height
                            }
                        }
                        .onEnded { value in
                        }
                )

处理向上的手势

首先我们需要一个值,代表手指移动页面向上的距离。可以使用一个 Text 来 显示 currentDragOffsetY 的值,观察 currentDragOffsetY 的值来判断向上移动多少距离,就把整个页面全部显示出来

经过观察判断,我把向上的距离限定为-150

ini 复制代码
.onEnded { value in
                            withAnimation(.spring()) {
                                if currentDragOffsetY < -150 {
 endingOffsetY = -startingOffsetY
                                } 
                                currentDragOffsetY = 0
                            }
                        }

页面拖动过程中,越往上 currentDragOffsetY值就越小 ,所以当视图向上距离小于 -150 时,我们就把 endingOffsetY 的值变成 startingOffsetY 值的负值, 然后吧 currentDragOffsetY 设置为零, 如果不设置为零就会有多个值影响offset。

向上的手势处理好了,但是向下的没有处理,所以还是有问题。

处理向下的手势

试图的位置停留在了顶部,当我们再往下拖动时,当前位移的值 currentDragOffsetY 会越来越大 ,我们还是让当前拖动值大于150 时,就让试图放在起始位置 startingOffsetY,然后要把 endingOffsetY 的值变成零。

同理 currentDragOffsetY 也要变成零。然后来看看整体效果

这种效果,在如今的app中非常常见。快快在你的app中使用起来吧。

大家有什么看法呢?欢迎留言讨论。

公众号:RobotPBQ

相关推荐
Jouzzy7 小时前
【iOS安全】Dopamine越狱 iPhone X iOS 16.6 (20G75) | 解决Jailbreak failed with error
安全·ios·iphone
瓜子三百克7 小时前
采用sherpa-onnx 实现 ios语音唤起的调研
macos·ios·cocoa
左钦杨8 小时前
IOS CSS3 right transformX 动画卡顿 回弹
前端·ios·css3
努力成为包租婆9 小时前
SDK does not contain ‘libarclite‘ at the path
ios
安和昂1 天前
【iOS】Tagged Pointer
macos·ios·cocoa
I烟雨云渊T1 天前
iOS 阅后即焚功能的实现
macos·ios·cocoa
struggle20251 天前
适用于 iOS 的 开源Ultralytics YOLO:应用程序和 Swift 软件包,用于在您自己的 iOS 应用程序中运行 YOLO
yolo·ios·开源·app·swift
Unlimitedz1 天前
iOS视频编码详细步骤(视频编码器,基于 VideoToolbox,支持硬件编码 H264/H265)
ios·音视频
安和昂2 天前
【iOS】SDWebImage源码学习
学习·ios
ii_best2 天前
按键精灵ios脚本新增元素功能助力辅助工具开发(三)
ios