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

相关推荐
missmisslulu7 小时前
电容笔值得买吗?2024精选盘点推荐五大惊艳平替电容笔!
学习·ios·电脑·平板
GEEKVIP8 小时前
手机使用技巧:8 个 Android 锁屏移除工具 [解锁 Android]
android·macos·ios·智能手机·电脑·手机·iphone
GEEKVIP8 小时前
如何在 Windows 10 上恢复未保存/删除的 Word 文档
macos·ios·智能手机·电脑·word·笔记本电脑·iphone
奇客软件9 小时前
iPhone使用技巧:如何恢复变砖的 iPhone 或 iPad
数码相机·macos·ios·电脑·笔记本电脑·iphone·ipad
奇客软件1 天前
如何从相机的记忆棒(存储卡)中恢复丢失照片
深度学习·数码相机·ios·智能手机·电脑·笔记本电脑·iphone
GEEKVIP2 天前
如何修复变砖的手机并恢复丢失的数据
macos·ios·智能手机·word·手机·笔记本电脑·iphone
一丝晨光2 天前
继承、Lambda、Objective-C和Swift
开发语言·macos·ios·objective-c·swift·继承·lambda
GEEKVIP2 天前
iPhone/iPad技巧:如何解锁锁定的 iPhone 或 iPad
windows·macos·ios·智能手机·笔记本电脑·iphone·ipad
KWMax2 天前
RxSwift系列(二)操作符
ios·swift·rxswift