SwiftUI:手势动画

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: 视图的显示和隐藏动画

赏我一个赞吧~~~

你可能感兴趣的:(SwiftUI:手势动画)