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

如何用SwiftUI实现类似Duolingo的选词填空横线效果?

SwiftUI单词排序组件改造:实现Duolingo式横线布局

需求说明

当前已实现单词点击移入指定区域的功能,需将原白色大容器替换为独立横线布局,让选中单词放置在横线上,效果匹配Duolingo的单词排序样式。

改造后代码(单行版本,适配长句子横向滚动)

ScrollView(.horizontal, showsIndicators: false) {
    HStack(spacing: 12) {
        ForEach(arrangedWords.indices, id: \.self) { index in
            let targetWord = arrangedWords[index]
            VStack(spacing: 4) {
                // 有单词时显示卡片
                if !targetWord.isEmpty {
                    Text(targetWord)
                        .foregroundColor(.white)
                        .padding(.horizontal, 16)
                        .padding(.vertical, 8)
                        .background(Color.green.opacity(0.8))
                        .cornerRadius(8)
                        .animation(.spring(), value: arrangedWords)
                        .onTapGesture {
                            moveWordOutOfSpace(index: index)
                            print("arranged words: \(arrangedWords)")
                        }
                }
                // 始终显示横线占位
                Rectangle()
                    .fill(Color.gray)
                    .frame(height: 3)
                    .frame(minWidth: 60) // 可根据单词长度调整横线最小宽度
            }
        }
    }
    .padding(.vertical, 16)
    .padding(.horizontal, 10)
}

改造后代码(多行版本,保留原布局逻辑)

ScrollView {
    VStack(alignment: .leading, spacing: 16) {
        ForEach(0..<(arrangedWords.count + itemsPerRow - 1) / itemsPerRow, id: \.self) { row in
            HStack(spacing: 12) {
                ForEach(0..<itemsPerRow, id: \.self) { wordIdx in
                    let index = row * itemsPerRow + wordIdx
                    if index < arrangedWords.count {
                        let targetWord = arrangedWords[index]
                        VStack(spacing: 4) {
                            if !targetWord.isEmpty {
                                Text(targetWord)
                                    .foregroundColor(.white)
                                    .padding(.horizontal, 16)
                                    .padding(.vertical, 8)
                                    .background(Color.green.opacity(0.8))
                                    .cornerRadius(8)
                                    .animation(.spring(), value: arrangedWords)
                                    .onTapGesture {
                                        moveWordOutOfSpace(index: index)
                                        print("arranged words: \(arrangedWords)")
                                    }
                            }
                            Rectangle()
                                .fill(Color.gray)
                                .frame(height: 3)
                                .frame(minWidth: 60)
                        }
                    }
                }
            }
        }
    }
    .padding(.vertical, 10)
    .padding(.horizontal, 10)
}

关键改动说明

  • 移除大容器样式:删掉原代码中background(.white)、cornerRadius(10)及边框overlay,改用每个位置独立的横线作为占位
  • 布局结构调整:用VStack将单词卡片(非空时显示)和横线垂直排列,实现单词悬浮在横线上的效果
  • 视觉细节优化:调整单词卡片的内边距、圆角,贴近Duolingo的设计风格;给横线设置最小宽度,避免空位置横线过窄
  • 滚动逻辑适配:单行版本使用横向ScrollView,适合长句子排版;多行版本保留原有的行拆分逻辑,适配多单词场景

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.15 22:13:17