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

SwiftUI实现字符串逐字符展示及数组字符串轮询切换

实现SwiftUI字符串数组的逐字符展示+循环切换效果

要实现逐字符展示每个字符串、完成后再切换下一个的效果,我们需要新增状态变量跟踪当前字符串的已展示字符数,同时调整计时器逻辑,分逐字符展示和切换字符串两个阶段执行。以下是修改后的完整代码:

struct ContentView: View {
    @State private var currentIndex: Int = 0
    @State private var currentCharCount: Int = 0
    
    var fontColor: String
    var displayData: [String]
    
    // 双计时器分工:控制逐字符展示、控制字符串切换
    private let charTimer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
    private let switchTimer = Timer.publish(every: 2.0, on: .main, in: .common).autoconnect()
    
    var body: some View {
        ZStack {
            // 展示当前字符串的前currentCharCount个字符
            Text(currentDisplayText)
                .foregroundColor(Color(hex: fontColor))
                .font(.uiFont(.subtitle3))
                .animation(.easeInOut(duration: 0.2), value: currentCharCount)
        }
        .onReceive(charTimer) { _ in
            guard !displayData.isEmpty else { return }
            let currentString = displayData[currentIndex]
            if currentCharCount < currentString.count {
                currentCharCount += 1
            } else {
                // 字符串展示完成,暂停逐字符计时器
                charTimer.upstream.connect().cancel()
            }
        }
        .onReceive(switchTimer) { _ in
            guard !displayData.isEmpty else { return }
            // 切换到下一个字符串
            currentIndex = (currentIndex + 1) % displayData.count
            // 重置字符计数并重启逐字符计时器
            currentCharCount = 0
            _ = charTimer.upstream.connect()
        }
        .onAppear {
            guard !displayData.isEmpty else { return }
            _ = charTimer.upstream.connect()
        }
    }
    
    // 计算当前要展示的文本
    private var currentDisplayText: String {
        guard !displayData.isEmpty else { return "" }
        let currentString = displayData[currentIndex]
        return String(currentString.prefix(currentCharCount))
    }
}

// 补充Color的hex扩展(如果你的项目中没有实现)
extension Color {
    init(hex: String) {
        let hex = hex.trimmingCharacters(in: CharacterSet.alphanumerics.inverted)
        var int: UInt64 = 0
        Scanner(string: hex).scanHexInt64(&int)
        let a, r, g, b: UInt64
        switch hex.count {
        case 3: // 12-bit RGB
            (a, r, g, b) = (255, (int >> 8) * 17, (int >> 4 & 0xF) * 17, (int & 0xF) * 17)
        case 6: // 24-bit RGB
            (a, r, g, b) = (255, int >> 16, int >> 8 & 0xFF, int & 0xFF)
        case 8: // 32-bit ARGB
            (a, r, g, b) = (int >> 24, int >> 16 & 0xFF, int >> 8 & 0xFF, int & 0xFF)
        default:
            (a, r, g, b) = (1, 1, 1, 0)
        }
        self.init(
            .sRGB,
            red: Double(r) / 255,
            green: Double(g) / 255,
            blue: Double(b) / 255,
            opacity: Double(a) / 255
        )
    }
}

// 补充UI Font扩展占位(替换成你项目中的实际逻辑)
extension Font {
    static func uiFont(_ style: some RawRepresentable) -> Font {
        return .system(size: 16)
    }
}

关键逻辑说明

  • 状态变量:currentIndex控制当前展示的数组元素,currentCharCount控制当前字符串已展示的字符数。
  • 双计时器分工:
    • charTimer:间隔0.2秒,负责逐字符增加计数,直到当前字符串全部展示完毕后暂停。
    • switchTimer:间隔2秒(需大于当前字符串逐字符展示的总时长),负责切换到下一个数组元素,重置字符计数并重启逐字符计时器。
  • 安全处理:添加了空数组判断,避免数组越界崩溃。

自定义调整方向

  • 修改charTimer的间隔(如0.15秒)可加快/减慢字符展示速度。
  • 修改switchTimer的间隔可调整每个字符串展示完成后的停留时间。
  • 替换动画效果(如.spring())可改变字符出现的动画风格。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:09:28