Last week I was working on one of the projects that required using UITextView instead of more standard UILabel instance. Don't get me wrong, but there were some compelling reasons for me to use UITextView. The reason being, I wanted to add a clickable link to the text and when user taps on it, execute a certain action.

The problem was not adding UITextView, but the spacing it keeps around. I will show you with an example below.

Let's make two UITextView instances and add it to view and see its layout by showing view frames.


override func viewDidLoad() {
        super.viewDidLoad()
        let textView1 = UITextView()
        let textView2 = UITextView()
        configure(textView: textView1, text: "Swift is the sweet language\nI can't wait to use this language with real apps")
        configure(textView: textView2, text: "Happy New Year to all people reading this post\nHope you all have this new wonderful year")

        let views = ["textView1": textView1, "textView2": textView2]
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-100-[textView1(>=0)][textView2(>=0)]", options: [], metrics: nil, views: views))
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-20-[textView1]-20-|", options: [], metrics: nil, views: views))
        self.view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-20-[textView2]-20-|", options: [], metrics: nil, views: views))
    }

    func configure(textView view: UITextView, text: String) {
        view.translatesAutoresizingMaskIntoConstraints = false
        view.isScrollEnabled = false
        view.isEditable = false
        view.text = text
        self.view.addSubview(view)
    }

And this is how result looks like,
(I have enabled view frame by going to Debug -> View Debugging -> Show View Frames)

text_view_demo

As you can see even though I have asked autolayout to maintain zero vertical spacing, you can still see unwanted padding on left, top and bottom of text view. This is the default setting for UITextView. But this is not how it sets up for UILabel. What can we do so that redundant padding is eliminated and UITextView appearance looks exactly like UILabel?

Turns out it is pretty simple and one line change. In the above code where we configure text views, we can add one more property on text view's content as follows.


// Remove all padding
view.textContainerInset = .zero

// Turns out we still have 5px of extra padding 
// on the left of text view. Code below gets rid of it too. 
// (Thanks to https://disqus.com/by/disqus_rrfMb06i8c/ for suggesting the update.)

// This option has a default value of 5.0. 
// So we set this option to 0.0 instead of 
// setting the view.contentInset

view.textContainer.lineFragmentPadding = 0.0 

That should be it. Now if you re-run your project, all the redundant padding will be lost.

Screen-Shot-2019-05-29-at-9.53.09-PM

As you can see from the updated screenshot, we got rid of all the padding. Hope it helps someone who is trying to use UITextView in place of UILabel to support clickable links and still wants to make it look like as if UILabel is in use

Ref: StackOverflow