SwiftUI允许我们将手势附加到任何视图,并且这些手势的效果也可以动画化。稍后,我们将更详细地介绍手势,但现在让我们尝试一些相对简单的操作:可以在屏幕上拖动的卡片,但是放开后,卡片会恢复到其原始位置。
首先,我们的初始布局:
struct ContentView: View {
var body: some View {
LinearGradient(gradient: Gradient(colors: [.yellow, .red]), startPoint: .topLeading, endPoint: .bottomTrailing)
.frame(width: 300, height: 200)
.clipShape(RoundedRectangle(cornerRadius: 10))
}
}
这样可以在屏幕中央绘制类似卡片的视图。我们想根据手指的位置在屏幕上移动它,这需要三个步骤。
- 首先,我们需要某种状态来存储其拖动量:
@State private var dragAmount = CGSize.zero
其次,我们要使用该值来影响卡片在屏幕上的位置。SwiftUI为此提供了一个专用的修饰符,称为offset()
,它使我们能够调整视图的X和Y坐标而无需在其周围移动其他视图。您可以根据需要传递离散的X和Y坐标,但是——并非巧合——offset()
也可以直接采用CGSize
。
- 因此,第二步是将此修改器添加到卡片中:
.offset(dragAmount)
现在到了重要的部分:我们可以创建一个DragGesture
并将其附加到卡上。拖动手势有两个额外的修饰符,在这里对我们有用:onChanged()
让我们在用户移动手指时都运行一个闭包,而onEnded()
让我们在用户将手指从屏幕上抬起时运行一个闭包,从而结束拖动。
这两个闭包都被赋予了一个参数,该参数描述了拖动操作——它开始的位置,当前的位置,移动的距离等等。对于我们的onChanged()
修饰符,我们将阅读拖动的translation
,它告诉我们拖动距起点有多远——我们可以将其直接分配给dragAmount
,以便我们的视图随手势一起移动。对于onEnded()
,我们将完全忽略输入,因为我们会将dragAmount
设置回零。
- 因此,现在将此修饰符添加到线性渐变的卡片中:
.gesture(
DragGesture()
.onChanged { self.dragAmount = $0.translation }
.onEnded { _ in self.dragAmount = .zero }
)
如果您运行该代码,您会看到现在可以拖动渐变卡片了,放开拖动时,它将跳回到中间。卡的偏移量由dragAmount
决定,而dragAmount
则由拖动手势设置。
现在一切正常,我们可以通过一些动画使该动作栩栩如生,我们有两个选择:
- 添加一个隐式动画以使拖动和释放具有动画效果
- 添加一个显式动画以使释放成为动画。
要查看前者的实际效果,请将此修改器添加到线性渐变中:
.animation(.spring())
拖动时,由于弹簧动画的作用,卡会稍有延迟地移到拖动位置,但是如果突然移动,它也会轻轻地过冲。
要查看实际的显示动画效果,请删除该animation()
修饰符,并将现有的onEnded()
拖动手势代码更改为此:
.onEnded { _ in
withAnimation(.spring()) {
self.dragAmount = .zero
}
}
现在,这张卡将立即随您的拖动移动(因为它没有被动画化),但是当您松开时,它将进行动画处理。
如果我们将偏移动画与拖动手势并稍加延迟相结合,则无需大量代码就可以创建非常有趣的动画。
为了证明这一点,我们可以将文本“ Hello SwiftUI”编写为一系列单独的字母,每个字母的背景颜色和偏移量都由某个状态控制。字符串只是稍微有点花哨的字符数组,因此我们可以从这样的字符串中获取真实的数组:Array("Hello SwiftUI")
。
无论如何,请尝试一下,看看你能想到什么:
struct ContentView: View {
let letters = Array("Hello SwiftUI")
@State private var enabled = false
@State private var dragAmount = CGSize.zero
var body: some View {
HStack(spacing: 0) {
ForEach(0..
如果您运行该代码,将会看到可以拖曳任何字母以使整个字符串都紧随其后,短暂的延迟会产生类似于蛇的效果。当您释放拖动时,SwiftUI还将添加颜色更改,即使字母移回中心也可以在蓝色和红色之间进行动画显示。
译自 Animating gestures
Previous: 控制动画堆栈 | Hacking with iOS: SwiftUI Edition | Next: 视图的显示和隐藏动画 |
---|
赏我一个赞吧~~~