Reputation: 766
I have tried everything to auto-resize my UILabel in Swift. I can autoresize the text when it is one line but when it is two lines it no longer works. The text in the UILabel changes often happening about every 10 seconds. The code I have tried is:
let direction = UILabel(frame: CGRect(x: 95, y: 10, width: screenWidth - 95, height:100))
direction.numberOfLines = 0
direction.adjustsFontSizeToFitWidth = true
direction.lineBreakMode = .byWordWrapping
direction.textAlignment = .center
direction.minimumScaleFactor = 0.2
direction.font = UIFont.boldSystemFont(ofSize: 40)
view.addSubview(direction)
direction.text = "Ffafdafafdfa fafda dfafaf afa"
func updateDirection(update: String){
direction.text = update
}
The original text "Ffafdafafdfa fafda dfafaf afa" will automatically resize but when updateDirection is called the font size with not be changed from 40. I have also tried setting the number of lines to 2 and removing the .byWordWrapping. How can I get my UILabel to resize automatically?
Upvotes: 1
Views: 4268
Reputation: 7534
UILabel
will consider its content size to be one line of text, even when numberOfLines
is set to a non-zero value, unless preferredMaxLayoutWidth
is also set.
In other words, it can't predict how to wrap the text without preferredMaxLayoutWidth
, so it doesn't plan to. It seems like during the autolayout process, a UILabel
doesn't know how to balance the priority between its width set by layout constraints outside of it and the wrapping of text.
So it doesn't exert any additional pressure (more than the height of one line) on the vertical dimension even when its Content Compression Resistance is higher than other views', because it will assume that by exerting pressure in the horizontal axis, its content will be displayed.
So the solution is to set preferredMaxLayoutWidth
, so that it is able to determine the height of the content after wrapping the text and then it uses that content size to negotiate layout with other views.
You probably want to avoid hard-coding the width of your UILabel
. Assuming that its container's width is not going to change based on autolayout, it should be safe to use that. In this case I'm in a UITableViewCell
or UICollectionViewCell
and the "title label" spans the full width of the cell.
override func layoutSubviews() {
// Tell the label it should wrap text at the same width as this cell's contentView.
titleLabel.preferredMaxLayoutWidth = contentView.frame.width
super.layoutSubviews()
}
Upvotes: 0
Reputation: 8986
Below code will keep the frame size
and adjust the font size
according with direction label content
.
let backgroundView = UIView(frame: CGRect(x: 5, y: UINavigationController().navigationBar.frame.height + UIApplication.shared.statusBarFrame.height, width: UIScreen.main.bounds.width - 10, height: UIScreen.main.bounds.width - 100))
let direction = UILabel()
override func viewDidLoad() {
super.viewDidLoad()
direction.backgroundColor = UIColor.green
direction.numberOfLines = 0
direction.textAlignment = .center
direction.font = UIFont.boldSystemFont(ofSize: 40)
direction.adjustsFontForContentSizeCategory = true
direction.adjustsFontSizeToFitWidth = true
direction.text = "This is some multiline label with a background colour" // Set or Initiate random function for your array here.
backgroundView.backgroundColor = UIColor.red
view.addSubview(backgroundView)
backgroundView.addSubview(direction)
Timer.scheduledTimer(timeInterval: 10.0, target: self, selector: #selector(random), userInfo: nil, repeats: true)
direction.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint(item: direction,
attribute: .leading,
relatedBy: .equal,
toItem: backgroundView,
attribute: .leadingMargin,
multiplier: 1.0,
constant: 0.0).isActive = true
NSLayoutConstraint(item: direction,
attribute: .trailing,
relatedBy: .equal,
toItem: backgroundView,
attribute: .trailingMargin,
multiplier: 1.0,
constant: 0.0).isActive = true
NSLayoutConstraint(item: direction,
attribute: .top,
relatedBy: .equal,
toItem: backgroundView,
attribute: .topMargin,
multiplier: 1.0,
constant: 0.0).isActive = true
NSLayoutConstraint(item: direction,
attribute: .bottom,
relatedBy: .equal,
toItem: backgroundView,
attribute: .bottomMargin,
multiplier: 1.0,
constant: 0.0).isActive = true
}
func random(sender: Timer) {
//Place your random func code here.
}
Output:
Upvotes: 2
Reputation: 1448
I will try this code It is use full
first create one function
func calchight(strin:String) -> CGFloat
{
let label = UILabel(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: CGFloat.greatestFiniteMagnitude))
label.numberOfLines = 0
label.text = strin
label.sizeToFit()
return label.frame.height + 2
}
then call this function in your right place, when you want to resize label
/--------------
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
let heit = self.calchight(strin: StringObject)
return (heit)
}
/--------------------------
this code is useful and not require Auto layout containers
Upvotes: 0
Reputation: 1325
Try using function sizetofit() after assigning text to your label. like:
direction.sizeToFit()
Upvotes: -1
Reputation: 3301
Try this without Constraints:
let direction = UILabel(frame: CGRect(x: 95, y: 10, width: 375 - 95, height:100))
direction.numberOfLines = 0
direction.adjustsFontSizeToFitWidth = true
direction.textAlignment = .center
direction.minimumScaleFactor = 0.2
direction.font = UIFont.boldSystemFont(ofSize: 40)
view.addSubview(direction)
direction.text = "Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard"
Upvotes: 0