Search code examples
iosswiftuitextviewnsattributedstringcore-text

How to format text like a blockquote within a UITextView


I am trying to familiarize myself with CoreText and I started by making my own note taking application.

I have regex in place in conjunction with AttributedStrings and am trying to essentially mimic the functionality of the StackOverflow text box I am typing in now.

I have all of the common things like:

bold

italics

headers

emphasis blocks

But I am struggling to make a block quote / code block.

Something like this where it breaks to its own line and creates a box that goes to the edge no matter how long the text is.

And it changes the background color

Is this even possible to do strictly using AttributedStrings? I've seen some old examples where HTML / CSS is injected but I was hoping I could accomplish it using some special NSAttributedStringKey combination.


Solution

  • Yes, it's possible. Here's a sample playground in Swift 3:

    import UIKit
    import PlaygroundSupport
    
    let richText = NSMutableAttributedString()
    
    let chunk0 = NSAttributedString(string: "But I am struggling to make a block quote / code block.\n\n")
    richText.append(chunk0)
    
    let paragraphStyle = NSMutableParagraphStyle()
    paragraphStyle.headIndent = 20
    // Note that setting paragraphStyle.firstLineHeadIndent
    // doesn't use the background color for the first line's
    // indentation. Use a tab stop on the first line instead.
    paragraphStyle.tabStops = [NSTextTab(textAlignment: .left, location: paragraphStyle.headIndent, options: [:])]
    
    let chunk1 = NSAttributedString(string: "\tSomething like this where it breaks to its own line and creates a box that goes to the edge no matter how long the text is.\n", attributes: [
        NSParagraphStyleAttributeName: paragraphStyle,
        NSBackgroundColorAttributeName: UIColor.yellow
    ])
    richText.append(chunk1)
    
    let chunk2 = NSAttributedString(string: "\nIs this even possible to do strictly using AttributedStrings?")
    richText.append(chunk2)
    
    let textView = UITextView(frame: CGRect(x: 0, y: 0, width: 120, height: 400))
    textView.backgroundColor = .white
    textView.attributedText = richText
    PlaygroundPage.current.liveView = textView
    

    Here's the output:

    result

    But it's important to keep in mind that UITextView is much less powerful (for layout and styling) than a web view. If you want to get fancy (like stackoverflow does with the darker line of color along the left edge of the blockquote box), you should just generate HTML and CSS and use a web view.