Невозможно управлять анимацией в форме?

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

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

Мне также непонятно, почему анимация VStack обрабатывается так иначе, чем просто текстовое поле, которое красиво скользит вниз, в то время как VStack, кажется, получает некоторую комбинацию.move и.opacity.

import SwiftUI
import PlaygroundSupport


struct ContentView: View {

    @State var showGoodAnimation = false
    @State var showBadAnimation = false

    var body: some View {
        Form {
            Toggle(isOn: self.$showGoodAnimation.animation(.easeInOut(duration: 1))) {Text("Yay!")}
            if self.showGoodAnimation {
                Text("I animate beautifully.")
            }
            Toggle(isOn: self.$showBadAnimation.animation(.easeInOut(duration: 1))) {Text("Boo!")}
            if self.showBadAnimation {
                VStack {
                    Text("Hi.").padding()
                    Text("I'm a hot mess.").padding()
                }
                .frame(height: 250)
                .transition(.scale)
            }
            Text("I'm just always here.")
        }
    }
}

PlaygroundPage.current.setLiveView(ContentView())

1 ответ

Предполагаю, что, вероятно, некоторое время назад этот вопрос обошелся, но в интересах тех, кто бьется головой о SwiftUI Form и тому подобное сейчас (как и я :-))

Оказывается, что формы, списки и (без сомнения) другие компоненты намеренно игнорируют настройку анимации, потому что они являются компонентами SwiftUI View «более высокого уровня» (в отличие от V и HStack).

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

Скорее всего, он спроектирован таким образом, потому что разработчик хочет большего контроля. Затем Apple считает, что поощрение их к использованию компонентов нижнего уровня будет менее болезненным, чем попытки обойти оптимизацию, которую они применили к компонентам представления более высокого уровня.

В любом случае, для определенного есть по крайней мере один аварийный люк, заключив View в контейнер и указав .animation(nil)модификатор (как упоминалось в ответе Asperi SO здесь.

Пример этого показан ниже для полноты; Лично я избегаю этого шаблона, так как подозреваю, что это что-то вроде ножного ружья.

      import PlaygroundSupport
import SwiftUI

struct ContentView: View {
    @State var showGoodAnimation = false
    @State var showBadAnimation = false

    var body: some View {
        Form {
            Toggle(isOn: self.$showGoodAnimation.animation(.easeInOut(duration: 1))) { Text("Yay!") }
            if self.showGoodAnimation {
                Text("I animate beautifully.")
            }
            Toggle(isOn: self.$showBadAnimation.animation()) { Text("Boo!") }
            VStack {
                if self.showBadAnimation {
                    List {
                        Text("I animated differently").padding()
                        Text("But am I a footgun?").padding()
                    }
                    .transition(.asymmetric(insertion: .slide, removal: .opacity))
                    .animation(.easeOut(duration: 5))
                }
            }
            .animation(nil)
            .transition(.slide)
            Text("I'm just always here.")
        }
    }
}

PlaygroundPage.current.setLiveView(ContentView())
Другие вопросы по тегам