SwiftUI динамически добавляет подпредставление, но анимация не работает - PullRequest
1 голос
/ 30 сентября 2019

Я хотел бы создать представление в SwiftUI, которое добавляет подпредставление динамически и с анимацией.

struct ContentView : View {
    @State private var isButtonVisible = false

    var body: some View {
        VStack {
            Toggle(isOn: $isButtonVisible.animation()) {
                Text("add view button")
            }

           if isButtonVisible {
                 AnyView(DetailView())
                      .transition(.move(edge: .trailing))
                      .animation(Animation.linear(duration: 2))
             }else{
                    AnyView(Text("test"))
            }
        }
    }
}

Приведенный выше код прекрасно работает с анимацией. однако, когда я перемещаю часть выбора вида в функцию, анимация больше не работает (так как я хочу динамически добавлять различные виды, поэтому я помещаю логику в функцию.)


struct ContentView : View {
    @State private var isButtonVisible = false
    var body: some View {
        VStack {
            Toggle(isOn: $isButtonVisible.animation()) {
                Text("add view button")
            }

            subView().transition(.move(edge: .trailing))
                     .animation(Animation.linear(duration: 2))   
    }

     func subView() -> some View {
         if isButtonVisible {
             return AnyView(DetailView())
         }else{
            return AnyView(Text("test"))
        }
    }
}

это выглядитдля меня абсолютно то же самое, но я не понимаю, почему они имеют другой результат. Может кто-нибудь объяснить мне, почему? а какие-нибудь лучшие решения? Большое спасибо!

1 Ответ

2 голосов
/ 30 сентября 2019

Вот ваш код, модифицированный таким образом, чтобы он работал:

struct ContentView : View {
    @State private var isButtonVisible = false

    var body: some View {
        VStack {
            Toggle(isOn: $isButtonVisible.animation()) {
                Text("add view button")
            }

            subView()
                .transition(.move(edge: .trailing))
                .animation(Animation.linear(duration: 2))
        }
    }

    func subView() -> some View {
        Group {
            if isButtonVisible {
                DetailView()
            } else {
                Text("test")
            }
        }
    }
}

Обратите внимание на две вещи:

  1. Два приведенных выше примера отличаются, поэтому вы получаете разные результаты. Первый применяет переход и анимацию к DetailView, затем стирает его с помощью AnyView. Второй тип стирает DetailView с AnyView, затем применяет переход и анимацию.
  2. Вместо того, чтобы использовать AnyView и стирание типов, я предпочитаю инкапсулировать условную логику в представлении Group. Затем вы возвращаете тип Group, который будет правильно анимироваться.
  3. Если вам нужны разные анимации для двух возможностей для вашего подпредставления, теперь вы можете применить их непосредственно к DetailView() или Text("test").

Обновление

Метод Group будет работать только с операторами if, elseif и else. Если вы хотите использовать переключатель, вам нужно будет обернуть каждую ветку в AnyView(). Однако это нарушает переходы / анимацию. Использование switch и настройка пользовательских анимаций в настоящее время невозможно.

...