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

SwiftUI中如何实现数组元素对应的Text视图依次淡入淡出?

问题:如何实现文本数组的逐个淡入淡出动画(避免堆叠)

我有一个字符串数组,想逐个将每个元素作为Text视图实现动画,需求如下:

  • 遍历数组
  • 每个Text视图带透明度变化+轻微位移的淡入动画
  • 停留一段时间供阅读
  • 通过透明度变化实现淡出效果

我写了这段代码,但现在所有视图会堆叠在一起,没法做到前一个淡出后再显示下一个:

Group {
    let dialogue = [
        "string1",
        "string2",
        "string3",
        "string4",
        "string5",
        "string6"
    ]
    
    ForEach(0..<dialogue.count, id: \.self) { index in
        Text("\(dialogue[index])")
            .frame(width: geometryProxy.size.width * 0.25, height: geometryProxy.size.width * 0.25, alignment: .center)
            .minimumScaleFactor(0.15)
            .multilineTextAlignment(.center)
            .foregroundStyle(.white)
            .font(.system(size: 25, weight: .medium, design: .serif))
            .background(.cyan.opacity(0.5))
            .opacity(hasPresentedDialogue ? 1 : 0)
            .offset(y: hasPresentedDialogue ? 0 : geometryProxy.size.height * 0.35 - geometryProxy.size.height * 0.375)
            .position(x: geometryProxy.size.width * 0.65, y: geometryProxy.size.height * 0.35)
            .animation(.easeInOut(duration: 0.75).delay(5 * Double(index)), value: hasPresentedDialogue)
    }
    .onAppear { withAnimation { hasPresentedDialogue.toggle() } }
}

核心问题

你当前用同一个hasPresentedDialogue开关控制所有视图的显隐,加上延迟动画后,所有视图只会按时间先后显示,但不会自动隐藏,最终导致堆叠。要实现逐个淡入淡出,必须精准跟踪当前显示的文本索引,而非用统一状态控制所有视图。

修正方案

下面是实现逐个淡入淡出的完整代码,通过跟踪当前索引+异步任务控制动画流程:

struct DialogueView: View {
    @State private var currentDialogueIndex = -1
    let dialogue = [
        "string1",
        "string2",
        "string3",
        "string4",
        "string5",
        "string6"
    ]
    // 可配置的动画参数
    private let fadeDuration = 0.75
    private let displayDuration = 3.0 // 文本停留时长(不含动画时间)
    private let transitionGap = 0.2 // 淡出到下一个淡入的间隔
    
    var body: some View {
        GeometryReader { geometryProxy in
            ZStack { // 用ZStack确保同一时间只有一个文本在视觉层最上方
                ForEach(dialogue.indices, id: \.self) { index in
                    Text(dialogue[index])
                        .frame(width: geometryProxy.size.width * 0.25, height: geometryProxy.size.width * 0.25, alignment: .center)
                        .minimumScaleFactor(0.15)
                        .multilineTextAlignment(.center)
                        .foregroundStyle(.white)
                        .font(.system(size: 25, weight: .medium, design: .serif))
                        .background(.cyan.opacity(0.5))
                        .opacity(currentDialogueIndex == index ? 1 : 0)
                        .offset(y: currentDialogueIndex == index ? 0 : geometryProxy.size.height * 0.025) // 简化位移计算
                        .position(x: geometryProxy.size.width * 0.65, y: geometryProxy.size.height * 0.35)
                        .transition(.opacity.combined(with: .move(edge: .bottom))) // 统一过渡动画
                }
            }
            .onAppear {
                Task { await startDialogueSequence() }
            }
        }
    }
    
    // 控制动画序列的异步任务
    private func startDialogueSequence() async {
        for index in dialogue.indices {
            // 淡入当前文本
            withAnimation(.easeInOut(duration: fadeDuration)) {
                currentDialogueIndex = index
            }
            // 等待文本停留时长
            try? await Task.sleep(nanoseconds: UInt64(displayDuration * 1_000_000_000))
            // 淡出当前文本
            withAnimation(.easeInOut(duration: fadeDuration)) {
                currentDialogueIndex = -1
            }
            // 等待过渡间隔(可选,优化衔接体验)
            try? await Task.sleep(nanoseconds: UInt64(transitionGap * 1_000_000_000))
        }
        // 如果需要循环播放,取消下面的注释
        // await startDialogueSequence()
    }
}

关键改动说明

  1. 用索引跟踪当前文本:用currentDialogueIndex替代统一开关,只有索引匹配的文本才会显示
  2. ZStack层级管理:所有Text放在ZStack中,确保同一时间只有一个文本处于可见状态,避免堆叠
  3. 异步任务控制流程:通过startDialogueSequence()按顺序执行「淡入→停留→淡出→等待」的循环,完全符合需求
  4. 简化动画逻辑:用transition统一定义淡入淡出+位移效果,代码更简洁易维护

如果需要循环播放整个序列,只需取消startDialogueSequence()末尾递归调用的注释即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 05:55:10