Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: How do style Text view with different font and colour on string subranges

Tags:

swift

swiftui

I want to style my Text view such that string it displays has different colours for each of 2 words. I know I can just use 2 x Text with different style. But then I should keep this string words in separate state variables. But I consider whether it is possible to define different .font().foregroundColor() for different parts of string.

There are also cases when there is longer lead and we want only first sentence or first word to be bolded, and remaining text to have regular font.

Any idea how to achieve this in SwiftUI?

like image 700
Michał Ziobro Avatar asked Nov 27 '19 13:11

Michał Ziobro


People also ask

How do I change text font in SwiftUI?

Hold the command key and click the text to bring up a pop-over menu. Choose Show SwiftUI Inspector and then you can edit the text/font properties.

Which command can be used to modify the color of the text which appears on screen?

You can change the color of text in your Word document. Select the text that you want to change. On the Home tab, in the Font group, choose the arrow next to Font Color, and then select a color. You can also use the formatting options on the Mini toolbar to quickly format text.

How to set custom font for a text view in SwiftUI?

Text is a view that displays one or more lines of text in SwiftUI. By default a text view draws a string using a system font with the body text style. Text("Hello, world!") Text view with body text style. We can override this default font with a custom one. We can set a custom font for a text view using font (_:) modifier.

What are the different types of fonts used in Swift?

Text ( "Simple Swift Guide" ). font (. headline ). bold (). italic () Text ( "Simple Swift Guide" ). font (. callout ). foregroundColor (. blue) In a second, more advanced tutorial, we’re going to learn how to use custom font family in your iOS app.

How do I display multiple lines of text in Swift?

To display multiple lines of text, use a new line character as a separator: Text ( "Simple Swift Guide" ) . bold () . italic () . underline () Change font type of the text (e.g., to use defined, system wide large title): Uniformly add extra space (in points) between individual text characters (e.g., spread characters apart):

How to set font-weight in Java?

There are many ways to set font-weight. You can do it through both Font and Text instance methods. Set font-weight via weight (_:) modifier. This is a Font instance method, so we use this on a font, not text. Text("Hello, world!")


1 Answers

You can alternate formatting on a String with a ForEach loop wrapped in an HStack, although that comes with its own issues. The following code will let you conditionally apply formatting based on the word's location in the string:

struct FancyTextView: View {

    let label: String

    var splicedLabel: [String] {
        return label.split(separator: " ").map(String.init)
    }

    var body: some View {
    
        HStack {
            ForEach(0..<splicedLabel.count, id: \.self) { index in
                Text(self.splicedLabel[index])
                    .fontWeight(index.isMultiple(of: 2) ? .bold : .regular)
                    .foregroundColor(index.isMultiple(of: 2) ? .blue : .red)
            }
        }
    
    }
}

String formatting example

Unfortunately, this simple solution doesn't work with longer strings:

Poor formatting for longer strings

I thought recursion might be useful, but I couldn't think of a way to use recursion with SwiftUI's Text() + Text() syntax.

Still, you could modify the above code to only format the first word with a larger font and then you could use the Text() + Text() syntax:

First word formatting

This also removes the unpleasant formatting of the HStack and ForEach combination with text. Just change the body to the following:

Text(splicedLabel[0] + " ")
        .font(.title)
        .fontWeight(.bold)
    + Text(splicedLabel[1])

If you use this example, make sure you change the maxSplits parameter in .split() to 1 and check to make sure that there are at least two strings in the resulting array.

like image 156
Lineous Avatar answered Sep 18 '22 12:09

Lineous