UILabel - How to add space between lines in Swift 3 - ios

I've UILabel with paragraphic information (multiline text) and I want add some spaces between lines, similar to this image.
Please help me to do it. I've tried to checkout all documentation of apple developer regarding Label and line spacing but could find.

From Interface Builder (Storyboard/XIB):
Programmatically:
SWift 4
Using label extension
extension UILabel {
// Pass value for any one of both parameters and see result
func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.lineHeightMultiple = lineHeightMultiple
let attributedString:NSMutableAttributedString
if let labelattributedText = self.attributedText {
attributedString = NSMutableAttributedString(attributedString: labelattributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
// Line spacing attribute
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
Now call extension function
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) . // try values 1.0 to 5.0
// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0
Or using label instance (Just copy & execute this code to see result)
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString
Swift 3
let label = UILabel()
let stringValue = "Sample text"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
label.attributedText = attrString

#IBOutlet weak var myLabel: UILabel!
let textForLabel = “Lorem Ipsum is simply dummy text of the printing and
typesetting industry. Lorem Ipsum has been the industry’s standard dummy text
ever since the 1500s, when an unknown printer took a galley of type and
scrambled it to make a type specimen book. It has survived not only five
centuries, but also the leap into electronic typesetting, remaining
essentially unchanged.”
let paragraphStyle = NSMutableParagraphStyle()
//line height size
paragraphStyle.lineSpacing = 1.4
let attrString = NSMutableAttributedString(string: titleText)
attrString.addAttribute(NSParagraphStyleAttributeName, value:paragraphStyle,
range:NSMakeRange(0, attrString.length))
myLabel.attributedText = attrString
myLabel.textAlignment = NSTextAlignment.Center

Related

show bullets in label on tableview cell swift ios

I have a table view, inside the table view I have multiple cells as shows in attached image.
I want to show amenities items like : air conditioning, swimming pool, gym, tv cable etc like bullets.
How can I achieve this
I have all these value in my model coming from API response.
let ac = "Air Conditioning"
let tv = "TV Cable"
let washing = "Washing Machine"
let connectivity = "Wi-Fi"
let gym = "Gym"
Good case for stack views...
Vertical UIStackView
Each "row" is a Horizontal UIStackView with Distribution: Fill Equally
Looks like this - showing Bounds Rectangles:
without the Bounds Rectangles:
view hierarchy:
Edit
A second approach (which you may find easier)...
Use a single horizontal stack view with a single label on each "side" and use .attributedText.
Set the .attributedText of each label to a formatted, bulleted attributed string.
The cell prototype could look like this:
Then, use this code (slightly modified from https://stackoverflow.com/a/46889728/6257435) to generate a formatted, bulleted attributed string:
func add(bulletList strings: [String],
font: UIFont,
indentation: CGFloat = 15,
lineSpacing: CGFloat = 3,
paragraphSpacing: CGFloat = 10,
textColor: UIColor = .black,
bulletColor: UIColor = .red) -> NSAttributedString {
func createParagraphAttirbute() -> NSParagraphStyle {
var paragraphStyle: NSMutableParagraphStyle
let nonOptions = NSDictionary() as! [NSTextTab.OptionKey: Any]
paragraphStyle = NSParagraphStyle.default.mutableCopy() as! NSMutableParagraphStyle
paragraphStyle.tabStops = [
NSTextTab(textAlignment: .left, location: indentation, options: nonOptions)]
paragraphStyle.defaultTabInterval = indentation
paragraphStyle.firstLineHeadIndent = 0
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.paragraphSpacing = paragraphSpacing
paragraphStyle.headIndent = indentation
return paragraphStyle
}
let bulletPoint = "\u{2022}"
let textAttributes: [NSAttributedString.Key: Any] = [.font: font, .foregroundColor: textColor]
let bulletAttributes: [NSAttributedString.Key: Any] = [.font: font, .foregroundColor: bulletColor]
let buffer = NSMutableAttributedString.init()
for string in strings {
var formattedString = "\(bulletPoint)\t\(string)"
// don't add newLine if it's the last bullet
if string != strings.last {
formattedString += "\n"
}
let attributedString = NSMutableAttributedString(string: formattedString)
let paragraphStyle = createParagraphAttirbute()
attributedString.addAttributes(
[NSAttributedString.Key.paragraphStyle : paragraphStyle],
range: NSMakeRange(0, attributedString.length))
attributedString.addAttributes(
textAttributes,
range: NSMakeRange(0, attributedString.length))
let string:NSString = NSString(string: formattedString)
let rangeForBullet:NSRange = string.range(of: bulletPoint)
attributedString.addAttributes(bulletAttributes, range: rangeForBullet)
buffer.append(attributedString)
}
return buffer
}
A quick implementation of that using your image as sample data results in this:

How to set both spacing between characters (kern) and strikethrough style for `UILabel`?

I need to set two attributes to a text presented by a UILabel: spacing between letters (kern), and its strikethrough style. Based on the NSAttributedStringKey documentation I have created the following extension to the UILabel:
extension UILabel {
func setStrikeThroughSpacedText(text: String, kern: CGFloat?) {
var attributes: [NSAttributedStringKey : Any] = [:]
if let kern = kern {
attributes[.kern] = kern
}
attributes[.strikethroughStyle]
= NSNumber(integerLiteral: NSUnderlineStyle.styleSingle.rawValue)
self.attributedText = NSAttributedString(string: text,
attributes: attributes)
}
}
However, it seems that .kern key somehow collides with the .strikethroughStyle key, because if I specify kern, the kern is applied, but not the strikethrough style. If I don't specify kern (so the extension does not apply the .kern attribute), the strikethrough style works.
Anyone has a different way how to work around this bug (I assume this is a bug)?
Try this, it should work for you
Note: I tested in Swift 4
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
let style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.count))
attrString.addAttribute(NSAttributedStringKey.strikethroughStyle, value: 2, range: NSMakeRange(0, attrString.length))
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString
Result:
Sim 1: Strike + LineSpacing
Sim 2: Strike + LineSpacing + Character Spacing

Is it possible to set a different colour for one character in a UILabel?

I've been working on a small project using Xcode. It uses a lot of labels, textfields, etc. I've finished with most of the layout, the constrains, and the forms, titles, etc. After which, the client announces that for all required fields, there should be a red asterisk next to the label.
Call me lazy, but I'd rather not go back to all of my forms, add in a lot of labels with asterisks on them, and re-do my auto-layout to accommodate the new labels.
So, is there a way to change the colour of a specific character (in this case, the asterisk) in a UILabel, while the rest of the text stays black?
You can use NSMutableAttributedString.
You can set specific range of your string with different color, font, size, ...
E.g:
var range = NSRange(location:2,length:1) // specific location. This means "range" handle 1 character at location 2
attributedString = NSMutableAttributedString(string: originalString, attributes: [NSFontAttributeName:UIFont(name: "Georgia", size: 18.0)!])
// here you change the character to red color
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor(), range: range)
label.attributedText = attributedString
Ref: Use multiple font colors in a single label - Swift
You can change a lot of attribute of String.
Ref from apple: https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSMutableAttributedString_Class/index.html
let text = "Sample text *"
let range = (text as NSString).rangeOfString("*")
let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSForegroundColorAttributeName, value: UIColor.redColor() , range: range)
//Apply to the label
myLabel.attributedText = attributedString;
UILabel have an .attributedText property of type NSAttributedString.
Declaration
#NSCopying var attributedText: NSAttributedString?
You let your asterix * have a single .redColor() attribute (NSForegroundColorAttributeName), whereas the rest of the new label simply uses the same text as before, however also contained in an NSAttributedTextString.
An example follows below using a function to repeatedly update your existing labels to attributed strings prefixed with a red *:
class ViewController: UIViewController {
#IBOutlet weak var myFirstLabel: UILabel!
#IBOutlet weak var mySecondLabel: UILabel!
let myPrefixCharacter = "*"
let myPrefixColor = UIColor.redColor()
// ...
override func viewDidLoad() {
super.viewDidLoad()
// ...
/* update labels to attributed strings */
updateLabelToAttributedString(myFirstLabel)
updateLabelToAttributedString(mySecondLabel)
// ...
}
func updateLabelToAttributedString(label: UILabel) {
/* original label text as NSAttributedString, prefixed with " " */
let attr = [ NSForegroundColorAttributeName: myPrefixColor ]
let myNewLabelText = NSMutableAttributedString(string: myPrefixCharacter, attributes: attr)
let myOrigLabelText = NSAttributedString(string: " " + (label.text ?? ""))
/* set new label text as attributed string */
myNewLabelText.appendAttributedString(myOrigLabelText)
label.attributedText = myNewLabelText
}
// ...
}
Swift 4
(Note: notation for attributed string key is changed in swift 4)
Here is an extension for NSMutableAttributedString, that add/set color on string/text.
extension NSMutableAttributedString {
func setColor(color: UIColor, forText stringValue: String) {
let range: NSRange = self.mutableString.range(of: stringValue, options: .caseInsensitive)
self.addAttribute(NSAttributedStringKey.foregroundColor, value: color, range: range)
}
}
Now, try above extension with UILabel and see result
let label = UILabel()
label.frame = CGRect(x: 40, y: 100, width: 280, height: 200)
let red = "red"
let blue = "blue"
let green = "green"
let stringValue = "\(red)\n\(blue)\n&\n\(green)"
label.textColor = UIColor.lightGray
label.numberOfLines = 0
let attributedString: NSMutableAttributedString = NSMutableAttributedString(string: stringValue)
attributedString.setColor(color: UIColor.red, forText: red) // or use direct value for text "red"
attributedString.setColor(color: UIColor.blue, forText: blue) // or use direct value for text "blue"
attributedString.setColor(color: UIColor.green, forText: green) // or use direct value for text "green"
label.font = UIFont.systemFont(ofSize: 26)
label.attributedText = attributedString
self.view.addSubview(label)
func updateAttributedStringWithCharacter(title : String, uilabel: UILabel) {
let text = title + "*"
let range = (text as NSString).range(of: "*")
let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
uilabel.attributedText = attributedString }
I know this is an old post, but i want to share my approach (which is based on the answer from dfri) i just made it a function for convenience.
func lastCharOnColor(label: UILabel, color: UIColor, length: Int) {
//First we get the text.
let string = label.text
//Get number of characters on string and based on that get last character index.
let characterCounter = string?.characters.count
let lastCharacterIndex = characterCounter!-1
//Set Range
let range = NSRange(location: lastCharacterIndex, length: length)
let attributedString = NSMutableAttributedString(string: string!, attributes: nil)
//Set label
attributedString.addAttribute(NSForegroundColorAttributeName, value: color, range: range)
label.attributedText = attributedString
}
I use this function to just set the last character from a label to a certain color like this:
lastCharOnColor(label: self.labelname, color: UIColor.red, length: 1)
Hope this helps anyone.
Here is an extension for simply making mandatory labels by appending a red *
Swift 5
extension UILabel {
func makeTextMandatory() {
let text = self.text ?? "" + " *"
let range = (text as NSString).range(of: " *")
let attributedString = NSMutableAttributedString(string:text)
attributedString.addAttribute(NSAttributedString.Key.foregroundColor, value: UIColor.red , range: range)
self.attributedText = attributedString
}
}
Usage :
dobLabel.makeTextMandatory()

How to implement UILabel line spacing using xib?

I want to align a UILabel's text vertically with line spacing via xib in iOS, for example:
hello,
how are
you?
Please help me.
Yes it is possible to adjust line spacing via xib. Click on UIlabel on xib,then change ‘text’ property type to ’Attributed’,then go through following images. Then enter new line(press ctrl-return shortcut key)and keep cursor in between two lines then adjust ‘line’ property and ‘Max Height’ property you want. My UILael text is "Hello,how are you?"
Create this simple UILabel subclass:
#interface CustomLabel : UILabel
#property (assign, nonatomic) CGFloat myLineSpacing;
#end
#implementation CustomLabel
- (void)setMyLineSpacing:(CGFloat)myLineSpacing {
_myLineSpacing = myLineSpacing;
self.text = self.text;
}
- (void)setText:(NSString *)text {
NSMutableParagraphStyle *paragraphStyle = [[NSMutableParagraphStyle alloc] init];
paragraphStyle.lineSpacing = _myLineSpacing;
paragraphStyle.alignment = self.textAlignment;
NSDictionary *attributes = #{NSParagraphStyleAttributeName: paragraphStyle};
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:text
attributes:attributes];
self.attributedText = attributedText;
}
Set myLineSpacing property value with IB.
Still you cannot preview in IB, but line spacing value is in xib!
You can set label.text in your code without caring about line spacing.
Note:
don't make property name "lineSpacing".
UILabel do have undocumented lineSpacing property, and overriding that breaks something.
*From Interface Builder:**
Programmatically:
SWift 4
Using label extension
extension UILabel {
// Pass value for any one of both parameters and see result
func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.lineHeightMultiple = lineHeightMultiple
let attributedString:NSMutableAttributedString
if let labelattributedText = self.attributedText {
attributedString = NSMutableAttributedString(attributedString: labelattributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
// Line spacing attribute
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
Now call extension function
let label = UILabel()
let stringValue = "How\nto\nimplement\nUILabel\nline\nspacing\nusing\nxib?"
// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) . // try values 1.0 to 5.0
// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0
Or using label instance (Just copy & execute this code to see result)
let label = UILabel()
let stringValue = "How\nto\nimplement\nUILabel\nline\nspacing\nusing\nxib?"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString
Type it exactly the same way you desire in any text editor like TextEdit etc and then paste in the text section of your label in xib.
But make sure height of your label is more to fit the content and also increase the number of lines. For this case it can be 3 or more.

How control line-spacing of UILabels?

I'm using CustomCell instead of UITableViewCell on UITableView.
I put two UILables on CustomCell.
Refered this site: here , but I failed...
Question : How can I control line spacing of UILabels?
Starting from iOS 6 you can set an attributed string to the UILabel. Check the following :
NSMutableParagraphStyle *paragrahStyle = [[NSMutableParagraphStyle alloc] init];
[paragrahStyle setLineSpacing:40];
[attributedString addAttribute:NSParagraphStyleAttributeName value:paragrahStyle range:NSMakeRange(0, [labelText length])];
cell.label.attributedText = attributedString;
Programmatically:
SWift 4
Using label extension
extension UILabel {
// Pass value for any one of both parameters and see result
func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
let paragraphStyle = NSMutableParagraphStyle()
paragraphStyle.lineSpacing = lineSpacing
paragraphStyle.lineHeightMultiple = lineHeightMultiple
let attributedString:NSMutableAttributedString
if let labelattributedText = self.attributedText {
attributedString = NSMutableAttributedString(attributedString: labelattributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
// Line spacing attribute
attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value:paragraphStyle, range:NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
Now call extension function
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
// Pass value for any one argument - lineSpacing or lineHeightMultiple
label.setLineSpacing(lineSpacing: 2.0) . // try values 1.0 to 5.0
// or try lineHeightMultiple
//label.setLineSpacing(lineHeightMultiple = 2.0) // try values 0.5 to 2.0
Or using label instance (Just copy & execute this code to see result)
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
// Line spacing attribute
attrString.addAttribute(NSAttributedStringKey.paragraphStyle, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
// Character spacing attribute
attrString.addAttribute(NSAttributedStringKey.kern, value: 2, range: NSMakeRange(0, attrString.length))
label.attributedText = attrString
Swift 3
Just copy & execute this code to see result.
let label = UILabel()
let stringValue = "How to\ncontrol\nthe\nline spacing\nin UILabel"
let attrString = NSMutableAttributedString(string: stringValue)
var style = NSMutableParagraphStyle()
style.lineSpacing = 24 // change line spacing between paragraph like 36 or 48
style.minimumLineHeight = 20 // change line spacing between each line like 30 or 40
attrString.addAttribute(NSParagraphStyleAttributeName, value: style, range: NSRange(location: 0, length: stringValue.characters.count))
label.attributedText = attrString
From Interface Builder:

Resources