skip to Main Content

I have a SwiftUI expandable FAQ view with Question text that I want bold and Answer text that I want to leave as non-bold text.

I am only able to make either BOTH bold OR both regular weight but want to know if it is possible to selective make the question text bold only??

Below is my code and screen-shot of what I have so far.

enter image description here

FAQ VIEW

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")])
}

DATA MODEL

struct QuestionAnswer: Identifiable {
    let id = UUID()
    let textOne: String
    var textTwo: [QuestionAnswer]?
}

4

Answers


  1. You could check if a row has any children to decide whether to bold the text or not.

    List(questionItems, children: .textTwo) { item in
        if item.hasChildren {
            Text(item.textOne)
                .bold()
                .padding([.top, .bottom], 15)
        } else {
            Text(item.textOne)
                .padding([.top, .bottom], 15)
        }
    }
    
    extension QuestionAnswer {
        var hasChildren: Bool { !(textTwo?.isEmpty == true) }
    }
    

    Or with suggested approach from the comments

    List(questionItems, children: .textTwo) { item in
        Text(item.hasChildren ? "**(item.textOne)**" : item.textOne )
            .padding([.top, .bottom], 15)
    }
    
    Login or Signup to reply.
  2. You could use this trick from the docs here: https://developer.apple.com/documentation/swiftui/list

    struct FileItem: Hashable, Identifiable, CustomStringConvertible {
            var id: Self { self }
            var name: String
            var children: [FileItem]? = nil
            var description: String {
                switch children {
                case nil:
                    return "📄 (name)"
                case .some(let children):
                    return children.isEmpty ? "📂 (name)" : "📁 (name)"
                }
            }
        }
    

    Except instead of changing an icon in the description, you would add the ** suggested by @Joakim Danielson

    Login or Signup to reply.
  3. The other approach you can do is below one

    var body: some View {
            VStack{
                List{
                    ForEach(questionItems) { item in
                        DisclosureGroup {
                            ForEach(item.textTwo ?? [QuestionAnswer]()) { innterItem in
                                Text(innterItem.textOne)
                            }
                        } label : {
                            Text(item.textOne)
                                .bold()
                        }
                    }
                }
                .foregroundColor(.black)
                .clipped()
            }
            .navigationBarTitle("Frequently asked questions", displayMode: .inline)
            .navigationBarBackButtonHidden(true)
    
        }
    

    enter image description here

    Login or Signup to reply.
  4. you may use attributed string .

    extension Text {
        init(_ string: String, configure: ((inout AttributedString) -> Void)) {
            var attributedString = AttributedString(string) 
            configure(&attributedString) 
            self.init(attributedString) // Text initialization
        }
    }
    

    Usage:

    Text("Your Text") { string in
                string.foregroundColor = .Color
                if let range = string.range(of: "Attributed") { 
                    string[range].foregroundColor = .YourColor // Use Your Style
                }
            }
    

    Use anywhere you need .
    for your current problem use attributed string on your list . and you may design as you can .

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search