Как в SwiftUI анимировать изменение опубликованного представления? - PullRequest
1 голос
/ 09 мая 2020

Я хотел бы анимировать изменение представления.
В частности, я создал представление, в котором один из его дочерних элементов является изменяющимся представлением.

struct MasterView: View {

    @State var playerLeft: Bool = false
    @ObservedObject var viewModel: MasterViewModel

    var body: some View {
        ZStack {
            WaitPlayerBackView(isShowing: self.$playerLeft) {
                self.viewModel.currentView
            }
        }
    }
}

Модель представления - это класс ObservableObject. currentView изменяется методом, вызываемым из потока asyn c, например:

class MasterViewModel: ObservableObject {
    @Published var currentView: AnyView = AnyView(EmptyView())

    func changeView() {
        self.currentView = AnyView(NightView())
    }
}

Это похоже на копию Android фрагментов (простите за сравнение).
Как я могу оживить это Посмотреть изменение?
Я пробовал разные варианты, например:

self.viewModel.currentView.animate(.default)

или

struct MasterView: View {

    @State var playerLeft: Bool = false
    @ObservedObject var viewModel: MasterViewModel

    var body: some View {
        ZStack {
            WaitPlayerBackView(isShowing: self.$playerLeft) {
                self.viewModel.currentView
            }
        }.animate(self.viewModel.animate ? .easeIn(duration: 1) : .none)
    }
}

class MasterViewModel: ObservableObject {
    @Published var currentView: AnyView = AnyView(EmptyView())
    @Published var animate = false

    func changeView() {
        self.animate = false
        self.currentView = AnyView(NightView())
        self.animate = true
    }
}

Однако ни один из них не работал.
Вот как я вижу переход, когда изменение экземпляра currentView. Example of transitions

1 Ответ

1 голос
/ 09 мая 2020

Перенос инициализации вашего представления в MasterView все упрощает:

struct MasterView: View {

    @State var playerLeft: Bool = false
    @ObservedObject var viewModel: MasterViewModel

    var body: some View {
        ZStack {
            VStack { //this represents WaitPlayerBackView
                if viewModel.day { //here are the posibles views that self.viewModel.currentView could have
                    Text("DayView").transition(AnyTransition.opacity.animation(.easeInOut(duration: 1.0)))
                } else {
                    Text("NightView").transition(AnyTransition.opacity.animation(.(duration: 1.0)))
                }
            }
        }
    }
}

class MasterViewModel: ObservableObject {
    @Published var day: Bool = false

    init () {
        _ = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(changeView), userInfo: nil, repeats: true) //Only for testing
    }
    @objc func changeView() { //@objc is only for testing
        day.toggle()
    }
}
...