UILabel text alignment not working (Swift 4) - ios

I'm trying to align the text in a UILabel but it's not working. The text prints with the second line of the label hugging the left side of the label. How do I make both lines aligned in the center of the label? Thanks.
let bioTextView: UILabel = {
let tv = UILabel()
tv.text = "This is sample text for a bio label for a user on this platform."
tv.backgroundColor = .clear
tv.textColor = .white
tv.lineBreakMode = .byWordWrapping
tv.numberOfLines = 0
tv.textAlignment = NSTextAlignment.right
return tv
}()
Please find the below screenshot for the issue. My requirement is to fit the text in tow lines.

Try setting the alignment after you have added the view as a subview.
view.addSubview(self.bioTextView)
bioTextView.textAlignment = .center

Try this one:
let bioTextView: UILabel = {
let tv = UILabel()
tv.backgroundColor = .clear
tv.textColor = .white
tv.lineBreakMode = .byWordWrapping
tv.numberOfLines = 0
let textString = NSMutableAttributedString(
string: "This is sample text for a bio label for a user on this platform.",
attributes: [:])
let textRange = NSRange(location: 0, length: textString.length)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.alignment = .center
textString.addAttribute(NSAttributedString.Key.paragraphStyle, value: paragraphStyle, range: textRange)
tv.attributedText = textString
return tv
}()

If someone is using UIStackView and has encountered this problem: stackView.alignment can ruin label.textAlignment property. Simply remove stackView.alignment.

Update following line fo code will fix your issue:
tv.textAlignment = .center
This will align your label text to center.

Related

UITextView.attributedText, How to set numberOflines and lineBreakMode?

In some condition I have to use UITextView instead of UILabel(To make link attributes clickable).
Here is my code:
let attributedString = NSMutableAttributedString(string: "TestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTestTest")
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineBreakMode = .byTruncatingTail
attributedString.addAttribute(.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, attributedString.length))
And here is my textView:
private lazy var titleTextView: UITextView = {
let view = UITextView(frame: .zero, textContainer: nil)
view.isEditable = false
view.textContainerInset = .zero
view.textContainer.lineFragmentPadding = 0
view.textContainer.maximumNumberOfLines = 2 // Set numberOflines here!
view.textAlignment = .left
view.isScrollEnabled = false
view.delegate = self
return view
}()
But maximumNumberOfLines property don't work, it display only 1 line and followed by "..."
You need to set the lineBreakMode to a value that doesn't truncate.
Try
paragraphStyle.lineBreakMode = .byWordWrapping
When i set the linespacing property, the size computered by UITextView.sizeToFit() is not height enough to display more than 1 line.
But in UILabel, call sizeToFit will computer a appropriate height for you to display as more lines as you want.
Try:
view.textContainer.maximumNumberOfLines = 2
view.textContainer.lineBreakMode = .byTruncatingTail
removing linebreakmode of paragraphStyle used by attributed text works for me.

Swift UIlabels not showing properly in uistackview

I am trying to programatically add uilabels into a stackview but for some reason it is not showing up properly. Here is what I have:
let label = UILabel()
label.textColor = UIColor.black
label.text = "Text that goes before "
let matlabel = MTMathUILabel()
matlabel.labelMode = MTMathUILabelMode.text
matlabel.latex = "$\\frac{x}{y}$"
matlabel.textColor = UIColor.black
let endLabel = UILabel()
label.textColor = UIColor.black
label.text = "? after"
self.textStack.addArrangedSubview(label)
self.textStack.addArrangedSubview(matlabel)
self.textStack.addArrangedSubview(endLabel)
And here is what I get
You create a "endLabel" but you didn't set text on it. You mistakenly set text on "label" so it just override your "label" text. try the following code:
let label = UILabel()
label.textColor = UIColor.black
label.text = "Text that goes before "
let matlabel = MTMathUILabel()
matlabel.labelMode = MTMathUILabelMode.text
matlabel.latex = "$\\frac{x}{y}$"
matlabel.textColor = UIColor.black
let endLabel = UILabel()
endLabel.textColor = UIColor.black
endLabel.text = "? after"
self.textStack.addArrangedSubview(label)
self.textStack.addArrangedSubview(matlabel)
self.textStack.addArrangedSubview(endLabel)
Well, I think what you wanted to really do was:
self.textStack.addArrangedSubview(label)
self.textStack.addArrangedSubview(matlabel)
self.textStack.addArrangedSubview(endLabel)
But, to your point, the "label" is not appearing. Have you tried setting the alignment and distribution?

Swift 3 UILabel, how to word wrap after changing text

I have a UILabel which has been created programmatically and want to set the text property dynamically after its creation. I can word wrap it during init but not subsequently. After the title label text is changed it keeps one line, regardless of whether I set the number of lines to 2 or 0 and word wrap or not. After I change the title I want it to occupy 2 lines and the text is easily long enough for this to happen but it does not.
let titleLabel: UILabel = {
let label = UILabel()
label.textAlignment = .center
label.translatesAutoresizingMaskIntoConstraints = false
label.backgroundColor = .clear
label.layer.masksToBounds = true
label.numberOfLines = 0
label.lineBreakMode = NSLineBreakMode.byWordWrapping
label.textColor = .white
return label
}()
var titleLabelText: String? {
didSet {
titleLabel.text = titleLabelText
titleLabel.layoutIfNeeded()
}
}
then later...
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
titleLabelText = "some string which needs word wrapping"
}
titleLabel.heightAnchor.constraint(equalToConstant: 40.0).isActive = true
titleLabel.widthAnchor.constraint(equalToConstant: screenWidth - 90).isActive = true
Font size is UIFont(name: "Muli", size: 12)
Here is how I load my label in viewDidLoad() but the label.text is applied in viewDidAppear()
let headerStackView: UIStackView = {
let headerArray = [welcomeLabel]
let stackView = UIStackView(arrangedSubviews: headerArray)
When you set your label to display multiple line..Remember your label must have enough height that can hold your text to be display multiple line.
Try to increase height of your label, Check width is proper and then check with your code.
If your text gets increases decrease the font size, it will automatically show complete text in your label.
and set the label line space to 0 and allow word wrap property true
select your label and try this one
AFAIK You need to add it as attributedText, then create an NSAttributedString, with your string and attributes.
let paragraphStyleWithWordWrapping = NSMutableParagraphStyle()
paragraphStyleWithWordWrapping.lineBreakMode = .byWordWrapping
let attributedString = NSAttributedString(myString, [NSParagraphStyleAttributeName: paragraphStyleWithWordWrapping])
label.attributedText = attributedString

UILabel text truncation vs. line breaks in text

I have a UILabel that is put as titleView in the navigation bar. I want it to have 2 lines, where the first line can be truncated and the second is center aligned.
In code it looks more less like this:
let label = UILabel()
let text = NSAttributedString(string: "Long long long text\nsecond line")
label.attributedText = text
label.textAlignment = .Center
label.numberOfLines = 0
label.lineBreakMode = .ByTruncatingTail
label.sizeToFit()
self.navigationItem.titleView = label
The effect in case of the first line text is not exceeding available
space is like this:
It's pretty good, but when the first line text is longer than:
let text = NSAttributedString(string: "Very very very very very long text\nsecond line")
I want to achieve like below.
How it can be done? I experimented with numberOfLines and lineBreakMode but it's not worked.
change your line breakmode to ByTruncatingMiddle instead of ByTruncatingTail. Something like below,
label.lineBreakMode = .ByTruncatingMiddle
Hope this will help :)
Navigation Tittle with sub-Tittle (Multiline Navigation Tittle)
Use NSMutableAttributedString with UITextView instead of UILabel
(because, if tittle is large then UILabel lineBreakMode with .byTruncatingTail is not working for first line in UILabel)
func multilineNavigation(title:String,subTitle:String) {
DispatchQueue.main.async {
let titleAttributedStr = NSMutableAttributedString(string: title, attributes: [NSAttributedStringKey.foregroundColor: UIColor.orange,NSAttributedStringKey.font: UIFont(name: "Helvetica Neue", size: 17.0) ?? UIFont()])
let subTitleAttributedStr = NSMutableAttributedString(string: "\n\(subTitle)", attributes: [NSAttributedStringKey.foregroundColor: UIColor.green,NSAttributedStringKey.font: UIFont(name: "Helvetica Neue", size: 12.0) ?? UIFont()])
titleAttributedStr.append(subTitleAttributedStr)
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = 1
paragraphStyle.lineBreakMode = .byTruncatingTail
titleAttributedStr.addAttribute(.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, titleAttributedStr.length))
let textView = UITextView()
textView.attributedText = titleAttributedStr
textView.backgroundColor = .clear
textView.isUserInteractionEnabled = false
textView.textContainerInset = .zero
textView.textAlignment = .center
textView.frame = CGRect(x: 0, y: 0, width: textView.intrinsicContentSize.width, height: 44)
self.navigationItem.titleView = textView
}
}

Multiline Navigationbar Title

I am trying to set the title label in my navigation bar to allow multiple lines. I have custom navigation controller code that I am placing the multiline code into. I know that the code already there works, but my multiline part is not working.
let titleLabel = UILabel()
titleLabel.frame = CGRectMake(0, 0, self.navigationBar.frame.width, self.navigationBar.frame.height * 2)
titleLabel.numberOfLines = 0
titleLabel.lineBreakMode = .ByWordWrapping
navigationItem.titleView = titleLabel
But the text still runs off at the end. I've also tried putting this into the individual view controller itself, adding self.navigationController?. in front of navigationItem with the same results.
Is there something I'm missing in my code that would keep the title label from using multiple lines?
Here is a code example of how you can create a multiline navigationBar title
let label: UILabel = UILabel(frame: CGRectMake(0, 0, 400, 50))
label.backgroundColor = UIColor.clearColor()
label.numberOfLines = 2
label.font = UIFont.boldSystemFontOfSize(16.0)
label.textAlignment = .Center
label.textColor = UIColor.whiteColor()
label.text = "This is a\nmultiline string for the navBar"
self.navigationItem.titleView = label
Swift 5.x:
let label = UILabel()
label.backgroundColor = .clear
label.numberOfLines = 2
label.font = UIFont.boldSystemFont(ofSize: 16.0)
label.textAlignment = .center
label.textColor = .white
label.text = "This is a\nmultiline string for the navBar"
self.navigationItem.titleView = label
This is doable in a storyboard. Just drag a UIView into the Navigation bar, then drag a UILabel onto it in the document outline, set lines to 2 and alignment to center.
Use this to get the label position exactly as you want it:
let labelWidth = navBar.bounds.width - 110
let label = UILabel(frame: CGRect(x:(navBar.bounds.width/2) - (labelWidth/2), y:0, width:labelWidth, height:navBar.bounds.height))
label.backgroundColor = UIColor.clear
label.numberOfLines = 0
label.font = UIFont.boldSystemFont(ofSize: 13.0)
label.textAlignment = .center
label.textColor = UIColor.black
label.lineBreakMode = .byWordWrapping
label.text = loadedName
navBar.topItem?.title = nil
navBar.addSubview(label)
the 110 value in the top line is the spacing you want either side of the label.
swift 5+ very easy solution
func titleMultiLine(topText: String, bottomText: String) {
// let titleParameters = [NSForegroundColorAttributeName : UIColor.white,
// NSFontAttributeName : UIFont.<Font>]
// let subtitleParameters = [NSForegroundColorAttributeName : UIColor.<Color>(),
// NSFontAttributeName : UIFont.<Font>]
let titleParameters = [NSAttributedString.Key.foregroundColor : UIColor.white]
let subtitleParameters = [NSAttributedString.Key.foregroundColor : UIColor.white]
let title:NSMutableAttributedString = NSMutableAttributedString(string: topText, attributes: titleParameters)
let subtitle:NSAttributedString = NSAttributedString(string: bottomText, attributes: subtitleParameters)
title.append(NSAttributedString(string: "\n"))
title.append(subtitle)
let size = title.size()
let titleLabel = UILabel(frame: CGRect(x: 0, y: 0, width: size.width, height: size.height))
titleLabel.attributedText = title
titleLabel.numberOfLines = 0
titleLabel.textAlignment = .center
navigationItem.titleView = titleLabel
}
Function Calling
self.titleMultiLine(topText: "I am top text Title", bottomText: "bottom text")

Resources