web-dev-qa-db-fra.com

Modifier l'espacement des caractères sur UILabel dans Interface Builder

Est-il possible de changer l'espacement des caractères (piste) sur le texte UILabel à l'aide d'Interface Builder? Sinon, y a-t-il un moyen de le faire par programme sur un UILabel existant déjà créé avec du texte attribué?

45
codeman

Nous avons fini par utiliser ceci pour le moment pour obtenir le texte attribué existant et modifier pour ajouter un espacement des caractères:

let attributedString = discoveryTitle.attributedText as NSMutableAttributedString
attributedString.addAttribute(NSKernAttributeName, value: 1.0, range: NSMakeRange(0, attributedString.length))
discoveryTitle.attributedText = attributedString

Swift 3:

let attributedString = NSMutableAttributedString(string: discoveryTitle.text)
attributedString.addAttribute(NSKernAttributeName, value: CGFloat(1.0), range: NSRange(location: 0, length: attributedString.length))
discoveryTitle.attributedText = attributedString

Utiliser NSRange au lieu de NSMakeRange fonctionne dans Swift 3.

38
codeman

Je sais que ce n'est pas une solution d'Interface Builder, mais vous pouvez créer une extension UILabel, puis ajouter un espacement à n'importe quel UILabel de votre choix:

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

Envisagez de modifier la valeur par défaut kernValue de 1.15 à quelque chose qui fonctionne mieux avec votre conception.


Lors de la mise en œuvre toujours, ajoutez un espacement des caractères après avoir défini la valeur du texte:

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

Si vous envisagez d'avoir un espacement différent à différents endroits de l'application, vous pouvez remplacer la valeur de kern par défaut:

myLabelWithSpecialNeeds.addCharacterSpacing(kernValue: 1.3)
83
budidino

Pour un texte complètement statique , comme l’en-tête d’une vue ou plus particulièrement le launchScreen , vous pouvez insérer des lettres d’une largeur minime (par exemple, le caractère 'l') avec 0 opacity. Vous pouvez également définir la même couleur que l'arrière-plan.

Je suis conscient du fait que ce n'est pas la solution la plus jolie, mais c'est la seule solution qui fonctionne sans écrire de code et qui fait le travail - jusqu'à ce que vous puissiez le faire en spécifiant les attributs dans Xcode.

The resultHow to

Éditer/Idée supplémentaire: Pour que votre espacement soit encore plus variable, vous pouvez modifier la taille de la police des caractères de remplissage entre les deux. (Merci à @ mohamede1945 pour cette idée)

26
luk2302

Swift 3.2 et constructeur d'interface

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

enter image description here

15
Mike Glukhov

essaye ça!!

créer une classe CustomLabel

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

et définir l'attribut d'exécution

enter image description here

Note c'est en fait interligne (aussi appelé interligne .. dans les temps très anciens (pré-numérique), vous Je mettrais du plomb (le métal) entre les lignes pour augmenter l’écart entre les lignes. Pour l'espacement entre les lettres, cela s'appelle kerning .. voici comment faire le crénage https://stackoverflow.com/a/21141156/ 294884

9
Beslan Tularov

Pourquoi vous définissez tous NSMUTABLEAttributedString. Vous n'êtes pas obligé de définir explicitement la plage. Les emojis ont parfois l’air bizarre. Ceci est ma solution, testé dans Swift 4. ????

extension UILabel {
    func addCharactersSpacing(_ value: CGFloat = 1.15) {
        if let textString = text {
            let attrs: [NSAttributedStringKey : Any] = [.kern: value]
            attributedText = NSAttributedString(string: textString, attributes: attrs)
        }
    }
}
7
Adam Smaka

Inspiré par la réponse de budidinho, il s'agit d'une solution plus flexible lorsque vous souhaitez modifier l'espacement des étiquettes avec des interlignes différents. Au lieu d'aller à l'intérieur de la fonction et de changer la valeur, vous pouvez simplement la passer en tant que paramètre.

extension UILabel {
  func setTextSpacingBy(value: Double) {
    if let textString = self.text {
      let attributedString = NSMutableAttributedString(string: textString)
      attributedString.addAttribute(NSKernAttributeName, value: value, range: NSRange(location: 0, length: attributedString.length - 1))
      attributedText = attributedString
    }
  }
}
5
FredFlinstone

Swift 4 Extension UILabel:

import UIKit

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(NSAttributedString.Key.kern,
                                          value: newValue,
                                          range: NSRange(location: 0, length: attributedString.length))
            attributedText = attributedString
        }

        get {
            if let currentLetterSpace = attributedText?.attribute(NSAttributedString.Key.kern, at: 0, effectiveRange: .none) as? CGFloat {
                return currentLetterSpace
            } else {
                return 0
            }
        }
    }
}
4

Voici une solution pour Swift 4 qui ne remplacera pas les attributs de texte existants:

extension UILabel {

    /**
     Add kerning to a UILabel's existing `attributedText`
     - note: If `UILabel.attributedText` has not been set, the `UILabel.text`
     value will be returned from `attributedText` by default
     - note: This method must be called each time `UILabel.text` or
     `UILabel.attributedText` has been set
     - parameter kernValue: The value of the kerning to add
     */
    func addKern(_ kernValue: CGFloat) {
        guard let attributedText = attributedText,
            attributedText.string.count > 0,
            let fullRange = attributedText.string.range(of: attributedText.string) else {
                return
        }
        let updatedText = NSMutableAttributedString(attributedString: attributedText)
        updatedText.addAttributes([
            .kern: kernValue
            ], range: NSRange(fullRange, in: attributedText.string))
        self.attributedText = updatedText
    }
}
3
Max Paulson

Essaye ça. Il ajoutera l’espacement des caractères que vous affectez, que vous définissiez un texte simple ou un texte attribué.

open class UHBCustomLabel : UILabel {
    @IBInspectable open var characterSpacing:CGFloat = 1 {
        didSet {
            updateWithSpacing()
        }

    }

    open override var text: String? {
        set {
            super.text = newValue
            updateWithSpacing()
        }
        get {
            return super.text
        }
    }
    open override var attributedText: NSAttributedString? {
        set {
            super.attributedText = newValue
            updateWithSpacing()     
        }
        get {
            return super.attributedText
        }
    }
    func updateWithSpacing() {
        let attributedString = self.attributedText == nil ? NSMutableAttributedString(string: self.text ?? "") : NSMutableAttributedString(attributedString: attributedText!)
        attributedString.addAttribute(NSKernAttributeName, value: self.characterSpacing, range: NSRange(location: 0, length: attributedString.length))
        super.attributedText = attributedString
    }
}
2
Umair

Approche de programmation. (Essayez ceci, cela devrait fonctionner pour vous)
Note: J'ai testé dans Swift 4

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
1
Krunal

Vous pouvez utiliser l’extension Swift 4 UILabel suivante qui prend en compte le texte attribué existant et le texte brut afin de ne pas remplacer les paramètres existants:

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
    }
}
1
Soheil Novinfard