Сломанная анимация SwiftUI при использовании TabView

У меня есть рабочая анимация в представлении SwiftUI, которая прерывается, когда я помещаю это представление в, перехожу на другую вкладку и возвращаюсь. Как я могу это исправить?

Моя точка зрения более сложна, но я свел ее к следующему:

      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
    }
}

Вот запись этого кода на экране. При нажатии анимация плавно перемещается вверх и вниз. После перехода на Tab 2 и возвращаясь, когда я в первый раз нажимаю Move, он прыгает без анимации. Следующие нажатия снова анимируются.

На самом деле модель представления более сложная. Состояние (в данном случае: moved) изменяется через некоторое время после нажатия кнопки. Некоторая работа выполняется в фоновом потоке, а затем изменение состояния запускается в основном потоке. Вот почему я не могу переместить анимацию в Button действие.

Также вид более сложный. В RectView удаляется из глубины иерархии представлений и добавляется где-то совсем в другом месте.

Метод func animation(_ animation: Animation?)устарела в iOS 15. Проблема уже существует в iOS 14 навсегда. Я также попытался удалить animation модификаторы и поставьте moved = !moved в withAnimation { }блокировать. Все тот же результат.

Как я мог это исправить, сохранив TabView?

1 ответ

У вас была некоторая проблема с кодированием, вот рабочий код, также вам не нужен здесь:

      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
}
Другие вопросы по тегам