Drawing a simple line in a UILabel - ios

Is there a way to add a simple line through a UILabel. I have a 40px high UILabel and simply want to draw a black line horizontally through the middle (at 20px). Is there a way to do this without having to create an image and setting it as the background?

if your label consist text then you can use strike through in label like this.
Objective-C
NSString *newStringStrike = #"your text";
NSMutableAttributedString *attributeString = [[NSMutableAttributedString alloc] initWithString:newStringStrike];
[attributeString addAttribute:NSStrikethroughStyleAttributeName
value:#1
range:NSMakeRange(0, [attributeString length])];
labelName.attributedText = attributeString;

Yes, there are couple of ways. For example, you can add 1-point height subview to the label:
Swift 3.0 update:
let lineView = UIView(
frame: CGRect(x: 0,
y: label.bounds.size.height / 2,
width: label.bounds.size.width,
height: 1
)
)
lineView.backgroundColor = UIColor.black
label.addSubview(lineView)

You should be able to subclass UILabel and overwrite the drawRect method.

You can do it by using UILabel
height=1 width=as you need
and make its background colour as black and put it on your 40px UILabel. Hope this gonna help you.

#Anil solanki's answer using Swift 3.1:
let newStringStrike = "your text"
let attributeString = NSMutableAttributedString(string: newStringStrike)
attributedString.addAttribute(NSStrikethroughStyleAttributeName, value: 1, range: NSMakeRange(0, attributedString.length))
labelName.attributedText = attributedString

in swift4:
let newStringStrike = "your text"
let attributeString = NSMutableAttributedString(string: newStringStrike)
attributeString.addAttribute(NSAttributedStringKey.strikethroughStyle, value: 1, range: NSMakeRange(0, attributeString.length))
yourLabel = attributeString

simply create an NSAttributedString and assign to your label
let newStringStrike = "your text"
let attributeString = NSMutableAttributedString(string: newStringStrike)
attributeString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: 1, range: NSMakeRange(0, attributeString.length))
yourLabel.attributedText = attributeString

Based on previous answers you can define something like this for swift 5
extension UILabel{
func setTextWithStrike(text: String)
{
let attributedString = NSMutableAttributedString(string: text)
attributedString.addAttribute(NSAttributedString.Key.strikethroughStyle, value: 1, range: NSMakeRange(0, attributedString.length))
self.attributedText = attributedString
}
}
and then use it like this:
labelWithStike.setTextWithStrike(text: "text with strike")

Related

How do I avoid this while changing the character spacing of UITextView?

I am trying to change the character spacing of uitextview. However it changes whole appearance.
Screenshots:
Before adding the code
After adding the code
Code (as extension):
extension UITextView {
func addCharacterSpacing(kernValue: Double = 1.15) {
if let textValue = text, textValue.count > 0 {
let attributedString = NSMutableAttributedString(string: textValue)
attributedString.addAttribute(NSAttributedStringKey.kern, value: kernValue, range: NSRange(location: 0, length: attributedString.length - 1))
attributedText = attributedString
}
}
}
If you are using NSMutableAttributedString, so you should customize it fully in the same way with paragraph style and fonts for it or any other settings.
From the screenshots I see a problem with paragraph style, setup it manually to the textView:
let paragraph = NSMutableParagraphStyle()
paragraph.alignment = .center
textView.attributedText = NSAttributedString(
string: "string",
attributes: [.paragraphStyle: paragraph])

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

iOS 10.3: NSStrikethroughStyleAttributeName is not rendered if applied to a sub range of NSMutableAttributedString

A strikethrough (single, double, ...) added as attribute to an instance of NSMutableAttributedString is not rendered if the apply range is not the whole string range.
This happens using addAttribute(_ name: String, value: Any, range: NSRange), insert(_ attrString: NSAttributedString, at loc: Int), append(_ attrString: NSAttributedString), ...
Broken by Apple in early iOS 10.3 betas, and not fixed in 10.3 final.
Credit:
https://openradar.appspot.com/31034683
Setting the baseline offset seems to fix it:
[attributedStr addAttribute:NSBaselineOffsetAttributeName value:#0 range:NSMakeRange(0, 10)];
[attributedStr addAttribute:NSStrikethroughStyleAttributeName value:#2 range:NSMakeRange(0, 10)];
This is a known bug in iOS 10.3
Adding a NSBaselineOffsetAttributeName, as explained here, to the attributed string brings back the strikethrough line. Overriding drawText:in: can be slow especially on Collection View or Table View Cells.
Found a workaround for our specific scenario (we don't specify any styling with UILabel's properties, but all with NSAttributedString attributes):
/// This UILabel subclass accomodates conditional fix for NSAttributedString rendering broken by Apple in iOS 10.3
final class PriceLabel: UILabel {
override func drawText(in rect: CGRect) {
guard let attributedText = attributedText else {
super.drawText(in: rect)
return
}
if #available(iOS 10.3, *) {
attributedText.draw(in: rect)
} else {
super.drawText(in: rect)
}
}
}
NOTE: if you mix UILabel's styling properties with NSAttributedString attributes, you should think of creating a new attributed string before rendering, apply UILabel's styling on it and then re-apply all attributedText's attributes over it.
swift 3 working code tested with 10.3
let attributeString: NSMutableAttributedString = NSMutableAttributedString(string: "₹3500")
attributeString.addAttribute(NSBaselineOffsetAttributeName, value: 0, range: NSMakeRange(0, attributeString.length))
attributeString.addAttribute(NSStrikethroughStyleAttributeName, value: 1, range: NSMakeRange(0, attributeString.length))
productPriceLabel.attributedText = attributeString
Swift 4
let text = "Hello World"
let textRange = NSMakeRange(0, text.count)
let attributedText = NSMutableAttributedString(string: text)
attributedText.addAttribute(NSAttributedStringKey.strikethroughStyle,
value: NSUnderlineStyle.styleSingle.rawValue,
range: textRange)
myLabel.attributedText = attributedText
Its a bug known to Xcode 8.3 (8E3004b) / iOS 10.3, with this workaround NO extra line of code is need, just add [NSBaselineOffsetAttributeName:0] when declaring NSMutableAttributedString()
let attrStr = NSMutableAttributedString(string: YOUR_STRING_HERE, attributes: [NSBaselineOffsetAttributeName : 0])
// Now if you add the strike-through attribute to a range, it will work
attrStr.addAttributes([
NSFontAttributeName: UIFont.boldSystemFont(ofSize: 24),
NSStrikethroughStyleAttributeName: 1
], range: NSRange)
For Swift 5 NSBaselineOffsetAttributeName changed with kCTBaselineOffsetAttributeName and will change every new version.

How to increase the character spacing in UILabel

I am creating an app in >=iOS6. And I want to change the character spacing in UILabel. I have added the custom font "FUTURABT HEAVY" in my app but the Character are too close to eachother.
I have find the good code here to increase the character spacing. But if i tried to change it than my text became left- align in stead of center.
Please help me with this situation.
You should probably use NSAttributedString with NSKernAttributeName attribute
Here is a small example:
UILabel *label = [[UILabel alloc] initWithFrame:self.view.bounds];
NSString *string = #"Some important text";
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:string];
float spacing = 5.0f;
[attributedString addAttribute:NSKernAttributeName
value:#(spacing)
range:NSMakeRange(0, [string length])];
label.attributedText = attributedString;
[self.view addSubview:label];
Swift extension for this
extension UILabel {
func addCharactersSpacing(spacing:CGFloat, text:String) {
let attributedString = NSMutableAttributedString(string: text)
attributedString.addAttribute(NSAttributedString.Key.kern, value: spacing, range: NSMakeRange(0, text.count-1))
self.attributedText = attributedString
}
}
So you can use it
MyLabel.addCharactersSpacing(5, text: "Some Text")
Swift 4
extension UILabel {
func setCharacterSpacing(characterSpacing: CGFloat = 0.0) {
guard let labelText = text else { return }
let attributedString: NSMutableAttributedString
if let labelAttributedText = attributedText {
attributedString = NSMutableAttributedString(attributedString: labelAttributedText)
} else {
attributedString = NSMutableAttributedString(string: labelText)
}
// Character spacing attribute
attributedString.addAttribute(NSAttributedStringKey.kern, value: characterSpacing, range: NSMakeRange(0, attributedString.length))
attributedText = attributedString
}
}
Swift 3
let label = UILabel()
let stringValue = "Sample text"
let attrString = NSMutableAttributedString(string: stringValue)
attrString.addAttribute(NSKernAttributeName, 2: style, range: NSRange(location: 0, length: stringValue.characters.count))
label.attributedText = attrString
Here the code for Swift 5 with a handy extension :
extension UILabel {
func addCharactersSpacing(spacing: CGFloat, txt: String) {
let attributedString = NSMutableAttributedString(string: txt)
attributedString.addAttribute(NSAttributedString.Key.kern, value: spacing, range: NSRange(location: 0, length: txt.count))
self.attributedText = attributedString
}
}
Swift 4.2 with UILabel extension and #IBInspectable
extension UILabel {
#IBInspectable var letterSpacing: CGFloat {
get {
var range:NSRange = NSMakeRange(0, self.text?.count ?? 0)
let nr = self.attributedText?.attribute(NSAttributedString.Key.kern, at: 0, effectiveRange: &range) as! NSNumber
return CGFloat(truncating: nr)
}
set {
let range:NSRange = NSMakeRange(0, self.text?.count ?? 0)
let attributedString = NSMutableAttributedString(string: self.text ?? "")
attributedString.addAttribute(NSAttributedString.Key.kern, value: newValue, range: range)
self.attributedText = attributedString
}
}
}
NSString *strDigit= #"001";
NSString *strCrushImpact =[NSStringstringWithFormat:#"%d",[strDigit intValue]];
// Set space in between character
float spacing = 3.0f;
NSMutableAttributedString *attributedStrDigit = [[NSMutableAttributedString alloc] initWithString:strWin];
[strCrushImpact addAttribute:NSKernAttributeName value:#(spacing)
range:NSMakeRange(0, [strDigit length])];
label.attributedText = attributedStrDigit;

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