Home > OS >  How to contain overflowed UILabel's text inside UIView?
How to contain overflowed UILabel's text inside UIView?

Time:01-21

import UIKit

class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    view.backgroundColor = .systemBackground

    setup()
  }

  private func setup() {
    let container = UIView()
    container.backgroundColor = .red
    view.addSubview(container)
    
    container.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      container.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
      container.heightAnchor.constraint(equalToConstant: 100.0),
      container.widthAnchor.constraint(equalToConstant: 100.0)
    ])
    
    let label = UILabel()
    label.text = "This is my text.This is my text.This is my text.This is my text.This is my text.This is my text.This is my text."
    label.numberOfLines = 0
    label.sizeToFit()
    
    container.addSubview(label)
    
    label.translatesAutoresizingMaskIntoConstraints = false
    NSLayoutConstraint.activate([
      label.widthAnchor.constraint(equalTo: container.widthAnchor)
    ])
  }
}

I have a 100x100 UIView inside of which I want to add a UILabel. UILabel overflows the UIView. I want to know how I can contain UILabel inside UIView without overflowing?

I tried,

label.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
  label.topAnchor.constraint(equalTo: container.topAnchor),
  label.bottomAnchor.constraint(equalTo: container.bottomAnchor),
  label.widthAnchor.constraint(equalTo: container.widthAnchor)
])

But this for some reason adds vertical padding,

enter image description here

And activating those constraints also has another problem and that is when the text length is small, the text is vertically centered. I want to pin it to top left always.

enter image description here

CodePudding user response:

Here are my thoughts on what I think is happening.

I will start with the padding bit. I believe both these cases are actually the same:

UILabel Centering AutoLayout

The default behaviour is to center the text and in both cases this is happening. In the second case (image on the right) which you say there is a padding, the UILabel cannot fit another line of text at that font size and so it stops at line 4 and centers the text with the label's frame.

If you increase the label height to 500 for example, you will see that it is not a random padding, but rather a centering.

Here is a simple approximation of how many lines of text a given height might support.

let label = UILabel()
label.text = "This is my text.This is my text.This is my text.This is my text.This is my text.This is my text.This is my text."
label.numberOfLines = 0
label.sizeToFit()

// I added these line
print("Max lines that will fit: \(floor(100.0 / label.font.lineHeight))")
print("Max lines that will fit: \(floor(130.0 / label.font.lineHeight))")

The answer printed out is 4.0 and 6.0. As I increased your label height to 130 as follows, and it gave me 6 lines as approximated:

// Inside your set up function
container.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
    container.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    container.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
    container.heightAnchor.constraint(equalToConstant: 130.0),
    container.widthAnchor.constraint(equalToConstant: 100.0)
])

let label = UILabel()
label.text = "This is my text.This is my text.This is my text.This is my text.This is my text.This is my text.This is my text."
label.numberOfLines = 0
label.sizeToFit()

UILabel size top align autolayout

So I hope that explains the bit about the padding.

Now coming to how to prevent the overflow, I think your autolayout already prevents that. I think also adding clipsToBounds on the container will prevent the label from overflowing.

Finally, aligning the label to the top is a different question altogether. However there was a UILabel Align text to the top vertically

  •  Tags:  
  • Related