SwiftUI List开发FAQ视图能否仅将问题文本设置为加粗
SwiftUI FAQ视图分层级字体加粗实现方案
需求与问题描述
开发可展开层级的SwiftUI FAQ视图,要求实现:
- 问题文本设置为加粗样式
- 回答文本保持常规字重
当前遇到的问题:直接给行内Text添加.bold()修饰符时,问题和回答文本会全部变为加粗;不添加该修饰符则二者全部为常规字重,无法实现仅问题加粗的效果。
当前运行效果

现有实现代码
FAQ视图代码
struct FAQ: View { let questionItems : [QuestionAnswer] = [ qa1(), qa2(), qa3() ] var body: some View { VStack { List(questionItems, children: \.textTwo) { item in Text(item.textOne) //.bold() makes BOTH bold or regular without .padding([.top, .bottom], 15) } .foregroundColor(.black) .clipped() } .navigationBarTitle("Frequently asked questions", displayMode: .inline) .navigationBarBackButtonHidden(true) } } func qa1() -> QuestionAnswer { return .init(textOne: "Question one", textTwo: [.init(textOne: "Answer one")]) } func qa2() -> QuestionAnswer { return .init(textOne: "Question two", textTwo: [.init(textOne: "Answer two")]) } func qa3() -> QuestionAnswer { return .init(textOne: "Question three", textTwo: [.init(textOne: "Answer three")]) }
数据模型代码
struct QuestionAnswer: Identifiable { let id = UUID() let textOne: String var textTwo: [QuestionAnswer]? }
实现方案
该需求可以实现,出现样式统一生效问题的原因是:使用List(children:)构造层级列表时,所有层级的行都会复用同一个行内容构建闭包,没有对节点类型做区分。
最小修改方案
基于现有数据结构,直接在构建行内容时判断当前节点类型:问题节点存在非空的子节点数组(textTwo属性有值),回答节点没有子节点,据此判断是否应用加粗样式即可。
修改后的List核心代码:
List(questionItems, children: \.textTwo) { item in // 存在非空子节点即为问题节点,否则为回答节点 let isQuestionNode = !(item.textTwo?.isEmpty ?? true) Text(item.textOne) .bold(isQuestionNode) // 仅问题节点应用加粗 .padding([.top, .bottom], 15) }
扩展性优化方案
如果后续FAQ会出现多层级嵌套(比如回答下还有补充说明、二级问题等),可以直接在数据模型中新增类型标识字段,判断逻辑会更稳定,不受层级结构变化影响:
- 修改数据模型,新增节点类型标识:
struct QuestionAnswer: Identifiable { let id = UUID() let textOne: String var textTwo: [QuestionAnswer]? let isQuestion: Bool // 新增:是否为问题节点 }
- 初始化数据时传入对应标识:
func qa1() -> QuestionAnswer { return .init( textOne: "Question one", textTwo: [.init(textOne: "Answer one", textTwo: nil, isQuestion: false)], isQuestion: true ) } // qa2、qa3按相同逻辑修改即可
- 行内容构建时直接根据标识判断样式:
List(questionItems, children: \.textTwo) { item in Text(item.textOne) .bold(item.isQuestion) .padding([.top, .bottom], 15) }
内容的提问来源于stack exchange,提问作者kissues
相关产品推荐
相关产品推荐

