You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

实现LazyVGrid数据更新时的从右至左切换动画

解决方案

1. 重构选项数据结构

先给每个选项添加唯一标识,避免因字符串重复导致SwiftUI的Diff算法识别混乱。在ViewModel中定义一个带唯一ID的结构体:

struct ChoiceItem: Identifiable {
    let id = UUID()
    let text: String
}

然后将possibleChoices的类型修改为[ChoiceItem]:

@Published var possibleChoices: [ChoiceItem] = []

2. 更新ViewModel的选项生成逻辑

调整selectArrayOfChoices方法,生成带唯一ID的选项集合:

func selectArrayOfChoices() {
    var choices: [ChoiceItem] = []
    // 添加当前问题的正确选项
    let correctText = questionsToDisplay[currentQuestionIndex].nameFr
    choices.append(ChoiceItem(text: correctText))
    
    var count = 0
    while count < 3 {
        let randomText = questionsToDisplay.randomElement()!.nameFr
        // 确保随机选项不重复且不等于正确选项
        if !choices.contains(where: { $0.text == randomText }) && randomText != correctText {
            choices.append(ChoiceItem(text: randomText))
            count += 1
        }
    }
    choices.shuffle()
    possibleChoices = choices
}

3. 调整视图代码,添加整体切换动画

修改LazyVGrid的实现,给整个网格添加过渡动画,并在按钮点击时用withAnimation包裹数据更新操作:

LazyVGrid(columns: columns, spacing: 20) {
    ForEach(vmchoices.possibleChoices) { item in
        Button {
            print("Button taped")
            // 用withAnimation触发动画,同步更新数据
            withAnimation(.easeInOut(duration: 0.5)) {
                vmchoices.updateCurrentQuestion()
                vmchoices.selectArrayOfChoices()
            }
        } label: {
            Text(item.text)
                .bold()
                .multilineTextAlignment(.center)
                .frame(width: 130, height: 130)
                .padding(.horizontal)
                .font(.title3)
                .foregroundColor(Color.accentColor)
                .background {
                    Rectangle()
                        .fill(.white)
                        .shadow(color: .black.opacity(0.2), radius: 10)
                }
        }
    }
}
.padding(.horizontal)
// 设置不对称过渡:旧网格向左移出,新网格从右侧移入
.transition(.asymmetric(insertion: .move(edge: .trailing), removal: .move(edge: .leading)))
// 绑定动画到选项数组的变化,确保触发时机正确
.animation(.easeInOut(duration: 0.5), value: vmchoices.possibleChoices)

关键说明

  • 使用Identifiable结构体替代纯字符串数组,让SwiftUI能精准追踪每个元素的生命周期,避免出现随机的单个按钮动画。
  • 不对称过渡动画实现了整体网格从右到左的切换效果,配合withAnimation指定0.5秒的动画时长。
  • 移除了不必要的DispatchQueue延迟,直接在动画闭包中执行数据更新,保证动画与数据变化同步。

内容的提问来源于stack exchange,提问作者axeeeeelt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.23 00:38:35