你好,我编写了一个简单的代码,其中我创建了一个带有改变其位置的圆圈的动画。我希望当我点击该圆圈时动画停止,但无论我将动画设置为零,它都不会停止。也许我的方法在某种程度上是错误的。如果有人提供帮助,我会很高兴。
struct ContentView: View {
@State private var enabled = true
@State private var offset = 0.0
var body: some View {
Circle()
.frame(width: 100, height: 100)
.offset(y: CGFloat(self.offset))
.onAppear {
withAnimation(self.enabled ? .easeIn(duration: 5) : nil) {
self.offset = Double(-UIScreen.main.bounds.size.height + 300)
}
}
.onTapGesture {
self.enabled = false
}
}
}
Run Code Online (Sandbox Code Playgroud)
正如@Schottky 上面所说,该offset值已经被设置,SwiftUI只是动画更改。
问题是,当您点击圆圈时,onAppear不会再次调用,这意味着enabled根本不会检查,即使是它也不会阻止offset动画。
为了解决这个问题,我们可以引入一个Timer并做一些小的计算,iOS带有一个内置Timer类,可以让我们定期运行代码。所以代码看起来像这样:
struct ContentView: View {\n @State private var offset = 0.0\n // 1\n let timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()\n @State var animationDuration: Double = 5.0\n var body: some View {\n Circle()\n .frame(width: 100, height: 100)\n .offset(y: CGFloat(self.offset))\n .onTapGesture {\n // 2\n timer.upstream.connect().cancel()\n }\n .onReceive(timer) { _ in\n // 3\n animationDuration -= 0.1\n if animationDuration <= 0.0 {\n timer.upstream.connect().cancel()\n } else {\n withAnimation(.easeIn) {\n self.offset += Double(-UIScreen.main.bounds.size.height + 300)/50\n }\n }\n }\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n这将创建一个计时器发布者,要求计时器每秒触发一次0.1。它说计时器应该在main线程上运行,它应该在common运行循环上运行,这是您\xe2\x80\x99大多数时间想要使用的循环。(运行循环可以iOS在用户主动执行某些操作(例如在列表中滚动或点击按钮)时处理正在运行的代码。)
当您点击圆圈时,计时器会自动取消。
\n我们需要使用名为 的新修饰符手动捕获公告(出版物)onReceive()。它接受发布者作为其第一个参数(在这里它是我们的计时器)和一个作为第二个参数运行的函数,并且它将确保每当发布者发送其更改通知时调用该函数(在这种情况下,每个0.1 秒)。
每 0.1 秒后,我们减少动画的持续时间,当持续时间结束(duration = 0.0)时,我们停止计时器,否则我们继续减少offset.
查看使用计时器重复触发事件以了解更多信息Timer
| 归档时间: |
|
| 查看次数: |
3711 次 |
| 最近记录: |