【发布时间】:2021-11-27 00:24:49
【问题描述】:
我在 SwiftUI 视图中有一个工作动画,当我将该视图放入 TabView 时,它会中断,转到另一个选项卡并返回。我该如何解决?
我的观点比较复杂,但我归结为以下几点:
import SwiftUI
@main
struct AnimationTestApp: App {
var body: some Scene {
WindowGroup {
TabView {
ContentView()
.tabItem {
Text("Tab 1")
}
Text("Content 2")
.tabItem {
Text("Tab 2")
}
}
}
}
}
struct ContentView: View {
@StateObject private var viewModel = ViewModel()
@Namespace var namespace
var body: some View {
VStack {
Button(action: {
viewModel.move()
}) {
Text("Move")
}
ZStack() {
Rectangle()
.fill(.gray)
.frame(width: 300, height: 300, alignment: .center)
if viewModel.moved {
RectView()
.matchedGeometryEffect(id: 0, in: namespace, properties: .frame)
.animation(Animation.default.speed(0.5))
.offset(x: 0, y: -130)
} else {
RectView()
.matchedGeometryEffect(id: 0, in: namespace, properties: .frame)
.animation(Animation.default.speed(0.5))
.offset(x: 0, y: 130)
}
}
}
}
}
struct RectView: View {
var body: some View {
Rectangle()
.frame(width: 100, height: 30, alignment: .center)
}
}
final class ViewModel: ObservableObject {
@Published var moved = false
func move() {
moved = !moved
}
}
这是该代码的屏幕记录。当点击Move 时,RectView 会上下平滑动画。切换到Tab 2 并返回后,我第一次点击Move 时,它会在没有动画的情况下跳转。接下来的点击再次动画。
实际上,视图模型更复杂。状态(在本例中为:moved)在按下按钮后会更改一段时间。一些工作在后台线程上完成,然后在主线程上触发状态更改。这就是为什么我不能将动画移动到 Button 动作中的原因。
视图也更复杂。 RectView 已从视图层次结构的深处移除,并完全添加到其他位置。
func animation(_ animation: Animation?) 方法在 iOS 15 中已弃用。该问题已在 iOS 14 中永远存在。我还尝试删除animation 修饰符并将moved = !moved 放入withAnimation { } 块中。结果还是一样。
如何在保留TabView 的同时解决这个问题?
【问题讨论】:
-
澄清:在我的原始代码中,我有大约 40 个 RectViews(实际上它们比 rect 更复杂)。当状态改变时,它们中只有一两个在移动。它们深深嵌套在 ZStacks、VStacks、GeometryReaders 等的层次结构中。这就是为什么我需要使用matchedGeometryEffect 和offset。
标签: ios animation swiftui tabview swiftui-geometryeffect