ios 在 Interface Builder 中更改 UILabel 上的字符间距

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/27535901/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 04:04:01  来源:igfitidea点击:

Change character spacing on UILabel within Interface Builder

iosswiftuilabelinterface-builder

提问by codeman

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 was already created with attributed text?

无论如何使用Interface Builder更改UILabel文本上的字符间距(轨道)?如果没有,有没有办法在已经使用属性文本创建的现有 UILabel 上以编程方式执行此操作?

采纳答案by codeman

Ended up using this for now to get existing attributed text and modify to add character spacing:

现在最终使用它来获取现有的属性文本并修改以添加字符间距:

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

Swift 3:

斯威夫特 3:

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

Using NSRange instead of NSMakeRange works in Swift 3.

在 Swift 3 中使用 NSRange 而不是 NSMakeRange 可以工作。

回答by budidino

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

我知道这不是 Interface Builder 解决方案,但您可以创建一个UILabel扩展,然后为UILabel您想要的任何添加间距:

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 kernValuefrom 1.15to something that works better with your design.

考虑将默认值kernValue从更改为1.15更适合您的设计的内容。



When implementing alwaysadd 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:

如果您计划在应用程序的不同位置使用不同的间距,您可以覆盖默认的 kern 值:

myLabelWithSpecialNeeds.addCharacterSpacing(kernValue: 1.3)


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

该解决方案将覆盖你的,你可能有任何其他属性UILabelattributedText

回答by luk2302

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.

对于完全静态的文本,例如视图的标题或尤其是 launchScreen,您可以使用 插入占用少量宽度的字母(例如“l”字符)0 opacity。或者将其颜色设置为与背景相同。

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.

我知道这一事实,这不是最漂亮的解决方案,但它是唯一无需编写任何代码即可完成工作的解决方案 - 直到您可以通过在 Xcode 中指定属性来完成。

The resultHow 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 @mohamede1945for that idea)

编辑/附加想法:为了使您的间距更加可变,您可以更改其间填充字符的字体大小。(感谢@mohamede1945的想法)

回答by Mike Glukhov

Swift 3.2 & Interface builder

Swift 3.2 和界面构建器

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

在此处输入图片说明

回答by Beslan Tularov

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

在此处输入图片说明

Notethis 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

请注意,这实际上是行距(也称为领先.. 在过去(数字前)您会在行之间放置铅(金属)以增加行间距。对于字母之间的间距,这称为字距调整。 . 这是如何进行字距调整https://stackoverflow.com/a/21141156/294884

回答by Adam Smaka

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.

为什么你们都在定义 NSMUTABLEAttributedString。您不必明确设置范围。它使表情符号有时看起来很奇怪。这是我的解决方案,在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)
        }
    }
}

回答by FredFlinstone

Swift 5

斯威夫特 5

Inspired by budidinho's answer, this is a more flexible solution for when you want to change the spacing for labels with different line spacings. In stead of going inside the function and changing the value you can just pass it as a parameter.

受到 budidinho 的回答的启发,当您想要更改具有不同行距的标签的间距时,这是一个更灵活的解决方案。无需进入函数内部并更改值,您只需将其作为参数传递即可。

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

回答by Maciej

SWIFT 4UILabel extension:

SWIFT 4UILabel 扩展:

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

回答by Max Paulson

Here is a solution for Swift 4 that won't override existing text attributes:

这是 Swift 4 的解决方案,它不会覆盖现有的文本属性:

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

回答by Soheil Novinfard

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

您可以使用以下Swift 4UILabel 扩展,它同时考虑现有的属性文本和纯文本,以免覆盖现有设置:

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