Change character spacing on UILabel within Interface Builder

前端 未结 13 2557
说谎
说谎 2020-12-23 09:21

Is there anyway to change the character spacing (track) on UILabel text using Interface Builder? If not, is there a way to do it programmatically on an existing UILabel that

相关标签:
13条回答
  • 2020-12-23 09:30

    For completely static text, like the header of a view or especially the launchScreen, you can insert letters that take up a tiny amount of width (e.g. the 'l' character) with 0 opacity. Alternatively set its color to the same as background.

    I am aware of the fact, that is not the prettiest solution, but it is the only solution that works without writing any code and does the job - until you can do it by specifying the attributes in Xcode.

    The result How to

    Edit / Additional idea: To make your spacing even more variable you can change the font size of the filling charachters in between. (Thanks to @mohamede1945 for that idea)

    0 讨论(0)
  • 2020-12-23 09:34

    Why all of you are defining NSMUTABLEAttributedString. You don't have to set range explicitly. It makes emojis looks weird sometimes. This is my solution, tested in Swift 4.

    0 讨论(0)
  • 2020-12-23 09:35

    You can use the following Swift 4 UILabel extension which considers both existing attributed text and plain text in order to do not override the existing settings:

    import UIKit
    
    extension UILabel {
        func addCharacterSpacing(_ kernValue: Double = 1.30) {
            guard let attributedString: NSMutableAttributedString = {
                if let text = self.text, !text.isEmpty {
                    return NSMutableAttributedString(string: text)
                } else if let attributedText = self.attributedText {
                    return NSMutableAttributedString(attributedString: attributedText)
                }
                return nil
                }() else { return}
    
            attributedString.addAttribute(
                NSAttributedString.Key.kern,
                value: kernValue,
                range: NSRange(location: 0, length: attributedString.length)
            )
            self.attributedText = attributedString
        }
    }
    
    0 讨论(0)
  • 2020-12-23 09:39

    Swift 3.2 & Interface builder

    extension UILabel {
    
        @IBInspectable
        var letterSpace: CGFloat {
            set {
                let attributedString: NSMutableAttributedString!
                if let currentAttrString = attributedText {
                    attributedString = NSMutableAttributedString(attributedString: currentAttrString)
                }
                else {
                    attributedString = NSMutableAttributedString(string: text ?? "")
                    text = nil
                }
    
                attributedString.addAttribute(NSKernAttributeName,
                                               value: newValue,
                                               range: NSRange(location: 0, length: attributedString.length))
    
                attributedText = attributedString
            }
    
            get {
                if let currentLetterSpace = attributedText?.attribute(NSKernAttributeName, at: 0, effectiveRange: .none) as? CGFloat {
                    return currentLetterSpace
                }
                else {
                    return 0
                }
            }
        }
    }
    

    0 讨论(0)
  • 2020-12-23 09:40

    I know it's not an Interface Builder solution, but you can create a UILabel extension and then add spacing to any UILabel you want:

    extension UILabel {
      func addCharacterSpacing(kernValue: Double = 1.15) {
        if let labelText = text, labelText.count > 0 {
          let attributedString = NSMutableAttributedString(string: labelText)
          attributedString.addAttribute(NSAttributedStringKey.kern, value: kernValue, range: NSRange(location: 0, length: attributedString.length - 1))
          attributedText = attributedString
        }
      }
    }
    

    Consider changing the default kernValue from 1.15 to something that works better with your design.


    When implementing always add character spacing after setting the text value:

    myLabel.text = "We used to be so close"
    myLabel.addCharacterSpacing()
    

    If you plan to have different spacing at different places in the app, you can override the default kern value:

    myLabelWithSpecialNeeds.addCharacterSpacing(kernValue: 1.3)
    

    This solution overrides any other attributes you might have on your UILabel's attributedText.

    0 讨论(0)
  • 2020-12-23 09:40

    try this!!

    create CustomLabel class

    @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;
    }
    

    and set runtime attribute

    enter image description here

    Note this is actually line spacing (also called leading .. in the very old days (pre-digital) you'd put lead (the metal) between lines to increase the gap between lines. For spacing between letters, that is called kerning .. here's how to do kerning https://stackoverflow.com/a/21141156/294884

    0 讨论(0)
提交回复
热议问题