破碎的 SwiftUI 过渡

Broken SwiftUI Transitions

我有一个非常简单的视图修饰符来呈现吐司

struct ToastItemModifier<Item: Equatable, M: View>: ViewModifier {

    typealias Style = ToastStyle

    // MARK: - Environment

    @Environment(\.colorScheme)
    var colorScheme

    // MARK: - Properties

    private let style: Style

    private let item: Item?

    private let message: (Item) -> M

    @Binding
    private var isPresented: Bool

    init(item: Item?, isPresented: Binding<Bool>, @ViewBuilder message: @escaping (Item) -> M, style: Style) {
        self.style = style
        self.item = item
        self.message = message
        _isPresented = isPresented
    }

    /// Indicates if content is presented.
    private var contentIsPresented: Bool {
        item != nil && isPresented
    }

    private var animation: Animation {
        .easeInOut(duration: 1)
    }

    // MARK: - ViewModifier

    func body(content: Content) -> some View {
        ZStack {
            content
            ZStack {
                if let item = item, contentIsPresented {
                    overlay(item: item)
                        .transition(.asymmetric(insertion: .scale(scale: 0.5), removal: .opacity).animation(animation))
                }
            }
        }
            .onReceive(Timer.publish(every: 3, on: .main, in: .default).autoconnect().first()) { _ in
                isPresented = false
            }
    }

    private func overlay(item: Item) -> some View {
        HStack {
            Image(uiImage: style.image)
                .padding(.leading, 20)
            message(item)
                .font(Font.custom("DMSans-Bold", size: 18))
                .foregroundColor(.white)
                .padding(.trailing)
        }
            .frame(height: 66)
            .background(style.background(for: colorScheme))
            .cornerRadius(20)
            .edgesIgnoringSafeArea(.all)
            .shadow(color: Color.black.opacity(0.15), radius: 12, x: 0, y: 8)
    }
}

使用不对称过渡,我可以在插入时实现缩放,在移除时实现不透明度淡化。但是,将这些转换更改为 .slide.move 之类的转换会完全破坏转换。

SwiftUI 中的某些转换是否中断?我在 opacityscale 上取得了巨大的成功,但其他的似乎不起作用。

查看我对问题的评论(以上),我会将 animation 移至容器,例如

ZStack {
    if let item = item, contentIsPresented {
        overlay(item: item)
            .transition(.asymmetric(insertion: .scale(scale: 0.5), removal: .opacity))
    }
}
.animation(animation, value: isPresented)   // << here !!