简体   繁体   中英

How to subclass a UILabel in swift with letter spacing set to 1.5 using NSKernAttribute

I am trying to subclass a UILabel so that it has a default kerning set to 1.5 then i am going to use that in my app with multiple labels. goal is to have default kern set out of the box so i can avoid repeated code all over the place also labels are set as mix of attributed and regular text Example:

@IBoutlet weak var myLabel: CustomeLabelWithKern!
myLabel.attributedText = myAttributedText

@IBOutlet weak var myOtherLabelInADifferentViewController: CustomeLabelWithKern!
myOtherLabelInADifferentViewController.text "Foo Bar"

both of these label should have kern of 1.5

here is what i have so far

class CustomLabel: UILabel {
   var kerning: CGFloat = 1.5

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        setKerning(kerning)
    }

    private func setKerning(kern: CGFloat) {
        guard let text = self.text else { return }
        let range = NSRange(location: 0, length: text.characters.count)
        let mutableString = NSMutableAttributedString(attributedString: attributedText ?? NSAttributedString())
        mutableString.addAttribute(NSKernAttributeName, value: kern, range: range)
        attributedText = mutableString
    }
} 

Here is what i have so far i think i will use this solution for now if anyone comes up with a better one i will be happy to try that as well

class CustomLabel: UILabel {
    static var kerning: CGFloat = 1.5

    override func awakeFromNib() {
       super.awakeFromNib()
       setKerning(CustomLabel.kerning)
    }

    func setKerning(kern: CGFloat) {
        let text = self.text ?? ""
        let range = NSRange(location: 0, length: text.characters.count)
        let mutableString = NSMutableAttributedString(attributedString: attributedText ?? NSAttributedString())
        mutableString.addAttribute(NSKernAttributeName, value: kern, range: range)
        attributedText = mutableString
    }
}

I can use it like this in my viewController

mylabel.text = "Hello World!" // this should be set to 1.5 by default but what if i am setting my label dynamically? 
mylabel.setKerning(1.5) // Here i am passing the value so if the label is set dynamically set it will have correct spacing 

// This also works if some of my labels have attributed text 
myAttibutedLabel.attributedText = myAttributedText
myAttributedLabel.setKerning(1.5)

I think a this can be reduce to just an extension on UILabel class like so

extension UILabel {
    func setKerning(kern: CGFloat) {
        let text = self.text ?? ""
        let range = NSRange(location: 0, length: text.characters.count)
        let mutableString = NSMutableAttributedString(attributedString: attributedText ?? NSAttributedString())
        mutableString.addAttribute(NSKernAttributeName, value: kern, range: range)
        attributedText = mutableString
   }
}

How about subclassing UILabel like this:

class TestKerningLabel: UILabel {
 func addKerning(kerningValue: Double) {
    let attributedString = self.attributedText as! NSMutableAttributedString
    attributedString.addAttribute(NSKernAttributeName, value: kerningValue, range: NSMakeRange(0, attributedString.length))
    self.attributedText = attributedString
 }
}

And then use this in your VC:

let testLabel = TestKerningLabel()
testLabel.attributedText = NSAttributedString(string: "test")
testLabel.addKerning(kerningValue: 1.5)
view.addSubview(testLabel)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM