SwiftUI 动画:一些隐式过渡动画在 iOS 13 上被破坏了?

Mik*_*rdo 9 animation swiftui

在 Xcode 11.3.1 和 11.4 上测试:

将隐式动画附加到过渡时,某些过渡类型似乎已损坏。具体来说,任何与位置相关的转换都不会应用给定的隐式动画。.slide, .move,.offset坏了。.opacity.scale似乎确定。(详见附件)

显式动画似乎在所有情况下都能正常工作。

即使使用自定义复合过渡,与位置相关的子过渡也不会响应隐式动画。

这是一个错误,还是预期的行为?

如果您想根据隐式属性更改为特定 UI 元素触发多个不同的动画曲线,这似乎是一个问题。

在此处输入图片说明


struct MyExample: View {

    @State private var isShowing = true

    private let myAnimation = Animation.spring(response: 0.8, dampingFraction: 0.2, blendDuration: 3.0)
    var body: some View {
        VStack(spacing:20) {
            if self.isShowing {
                Text("Opacity").modifier(MyBigFont())
                    .transition(AnyTransition.opacity.animation(myAnimation))

                Text("Scale").modifier(MyBigFont())
                    .transition(AnyTransition.scale.animation(myAnimation))

                Text("Slide").modifier(MyBigFont())
                    .transition(AnyTransition.slide.animation(myAnimation))

                Text("Move").modifier(MyBigFont())
                    .transition(AnyTransition.move(edge: .trailing).animation(myAnimation))

                Text("Offset").modifier(MyBigFont())
                    .transition(AnyTransition.offset(x: 20, y: 0).animation(myAnimation))

                Text("Custom").modifier(MyBigFont())
                    .transition(AnyTransition.myCustomTransition.animation(myAnimation))
            }

            Spacer()

            Button(action: {
                self.isShowing.toggle()
            }) {
                Text("Implicit Toggle")
            }

            Button(action: {
                withAnimation(self.myAnimation) {
                    self.isShowing.toggle()
                }
            }) {
                Text("Explicit Toggle")
            }
        }
    }

}

struct MyBigFont: ViewModifier {
    func body(content: Content) -> some View {
        content
            .lineLimit(1)
            .padding()
            .background(Color.purple)
            .foregroundColor(.white)
            .cornerRadius(8)
            .font(Font.system(size: 21).bold())
    }
}

struct MyCustomTransition: ViewModifier {

    var isEnabled: Bool

    func body(content: Content) -> some View {

        if isEnabled {
            return content
                .offset(x: 20.0, y: 0.0)
                .opacity(0)
        } else {
            return content
                .offset(x: 0.0, y: 0.0)
                .opacity(1)
        }

    }
}

extension AnyTransition {
    static let myCustomTransition = AnyTransition.modifier(
        active: MyCustomTransition(isEnabled: true),
        identity: MyCustomTransition(isEnabled: false))
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        VStack {
            MyExample()
            Spacer()
        }
    }
}

Run Code Online (Sandbox Code Playgroud)

Asp*_*eri 5

为了使隐式过渡正确地具有动画效果,需要制作包含这些过渡的可动画化容器。

使用 Xcode 11.4 / iOS 13.4 进行测试。

演示

这是唯一的修复:

struct MyExample: View {

    @State private var isShowing = true

    private let myAnimation = Animation.spring(response: 0.8, dampingFraction: 0.2, blendDuration: 3.0)
    var body: some View {
        VStack(spacing:20) {
            if self.isShowing {

                ...      // all your code here

            }
        }.animation(myAnimation)    // << fix !!
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 但这不会触发附加到每个转换的隐式动画。它用显式动画覆盖它们。这与使用单个“withAnimation {}”包装属性更改的效果相同 (2认同)

Mik*_*rdo 5

根据 Javier 的说法,从 Xcode 11.2 开始,隐式过渡动画不再起作用

如果有人有新的信息,请回复。

请注意,自 XCode 11.2 起,过渡不再适用于隐式动画。

https://swiftui-lab.com/advanced-transitions/