Swift UI transition失效问题
Swift UI transition失效问题

Swift UI transition失效问题

问题分析

在学习Swift UI transition时,想要通过切换transition的值来显示各种动画的差异,因此设置了Picker选择器:

Picker("显示样式", selection: $selectedTransition) {
    ForEach(transitions, id: \.self) { transition in
        Text(transition)
    }
}
.pickerStyle(SegmentedPickerStyle())

在选择对应选项后,通过按钮来展示transition。

Form {
    if isShowingRed {
        Rectangle()
            .fill(.red)
            .frame(width: 200, height: 200)
            .transition(getTransition())  // 在视图插入或移除时生效
    }
}

但实际在展示中发现,无论如何点击按钮,图像显示的效果都是一样的。

经排查发现,问题在于Form具有特殊的布局行为,其布局和显示行为可能会限制某些动画效果,特别是涉及视图的插入和移除动画时,Form可能会干扰transition。

解决方案

这里可以采取两种方案:

一是在Form中添加VStack视图

Form {
    VStack {
        if isShowingRed {
            Rectangle()
                .fill(.red)
                .frame(width: 200, height: 200)
                .transition(getTransition())  // 在视图插入或移除时生效
        }
    }
}

二是移除Form:

if isShowingRed {
    Rectangle()
        .fill(.red)
        .frame(width: 200, height: 200)
        .transition(getTransition())  // 在视图插入或移除时生效
}

以下为本次案例的完整代码:

import SwiftUI

struct ContentView: View {
    
    @State private var isShowingRed = false
    @State private var selectedTransition = "scale"
    @State private var transitions = ["scale", "opacity", "slide", "move", "offset"]
    
    var body: some View {
        VStack {
            Form {
                Button("Tap Me") {
                    withAnimation {
                        isShowingRed.toggle()
                    }
                }
            }
            Form {
                Picker("显示样式", selection: $selectedTransition) {
                    ForEach(transitions, id: \.self) { transition in
                        Text(transition)
                    }
                }
                .pickerStyle(SegmentedPickerStyle())
            }
            Form {
                VStack {
                    if isShowingRed {
                        Rectangle()
                            .fill(.red)
                            .frame(width: 200, height: 200)
                            .transition(getTransition())  // 在视图插入或移除时生效
                    }
                }
            }
        }
    }
    
    func getTransition() -> AnyTransition {
        switch selectedTransition {
        case "scale":
            return .scale
        case "opacity":
            return .opacity
        case "slide":
            return .slide
        case "move":
            return .move(edge: .leading)
        case "offset":
            return .offset(x: 100, y: 0)
        default:
            return .scale
        }
    }
}

#Preview {
    ContentView()
}

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注