【问题标题】:Broken SwiftUI animation when using TabView使用 TabView 时 SwiftUI 动画损坏
【发布时间】: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


【解决方案1】:

你有一些糟糕的编码问题,这里是工作代码,你也不需要matchedGeometryEffect这里:

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()

    var body: some View {
        
        VStack {
            
            Button(action: { viewModel.moved.toggle() }) {
                Text("Move")
            }

            ZStack() {

                Rectangle()
                    .fill(Color.gray)
                    .frame(width: 300, height: 300, alignment: .center)
                
                RectView()
                    .offset(x: 0, y: viewModel.moved ? -130 : 130)
                    .animation(Animation.default.speed(0.5), value: viewModel.moved)
                
            }
        }
    }
}

struct RectView: View {
    var body: some View {
        Rectangle()
            .frame(width: 100, height: 30)
    }
}


final class ViewModel: ObservableObject {
    @Published var moved: Bool = false
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-14
    • 1970-01-01
    • 2020-07-12
    • 2023-04-02
    • 1970-01-01
    • 2023-03-24
    • 2021-11-18
    • 2013-09-21
    相关资源
    最近更新 更多