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

Ios 在Interface Builder中更改UILabel上的字符间距,ios,swift,uilabel,interface-builder,Ios,Swift,Uilabel,Interface Builder,是否仍然可以使用Interface Builder更改UILabel文本上的字符间距(轨迹)?如果没有,是否有办法在已使用属性文本创建的现有UILabel上以编程方式执行此操作?试试这个 创建CustomLabel类 @interface CustomLabel : UILabel @property (assign, nonatomic) CGFloat myLineSpacing; @end @implementation CustomLabel - (void)setMyLineSp

是否仍然可以使用Interface Builder更改UILabel文本上的字符间距(轨迹)?如果没有,是否有办法在已使用属性文本创建的现有UILabel上以编程方式执行此操作?

试试这个

创建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;
}
并设置运行时属性


注意这实际上是行距(也称为行距。在非常古老的年代(数字之前),你会放铅(金属)行与行之间增加行与行之间的间距。对于字母之间的间距,这称为字距调整。以下是如何进行字距调整

最后使用此方法获取现有的属性文本并进行修改以添加字符间距:

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

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

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

我知道,这不是最漂亮的解决方案,但它是唯一一个不用编写任何代码就能完成任务的解决方案——直到您可以通过在Xcode中指定属性来完成任务


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

我知道这不是界面生成器解决方案,但您可以创建一个
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
    }
  }
}
考虑将默认的
kernValue
1.15
更改为更适合您的设计


执行时,始终在设置文本值后添加字符间距:

myLabel.text = "We used to be so close"
myLabel.addCharacterSpacing()
如果您计划在应用程序中的不同位置使用不同的间距,则可以覆盖默认的kern值:

myLabelWithSpecialNeeds.addCharacterSpacing(kernValue: 1.3)


此解决方案将覆盖您在
UILabel
attributedText
上可能具有的任何其他属性

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

编程方法。(试试这个,它应该适合你)
注:我在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

为什么你们都在定义NSMutableAttributeString。你们不必显式地设置范围。这有时会让表情看起来很奇怪。
这是我的解决方案,在Swift 4中测试

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

尝试此操作。它将添加您指定的字符间距,您可以设置简单文本或属性文本

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

以下是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
    }
}

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

您可以使用以下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
    }
}

Swift 5.3.1

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

这是我的字母间距代码。创建自定义标签类并从故事板设置字母间距。Swift 5

导入UIKit
类SpacingLabel:UILabel{
@我看得见
变量字母间距:双精度=0
覆盖公共变量文本:字符串{
迪塞特{
self.addCharacterSpacing(字母间距)
}
}
func addCharacterSpacing(kernValue:Double){
如果让labelText=text,则labelText.count>0{
让attributedString=NSMutableAttributedString(字符串:labelText)
attributedString.addAttribute(NSAttributedString.Key.kern,值:kernValue,范围:NSRange(位置:0,长度:attributedString.length-1))
attributedText=attributedString
}
}
}


我99%确定Xcode 6不支持此功能。@Drux我99%确定Xcode 6可以执行IBDesignablesAwesome解决方案!:)您甚至可以使用“|”字符的字体大小控制宽度。你所需要的只是创建一个并复制/粘贴:)@mohamede1945好主意,在我真正阅读你的评论并再次阅读我的答案之前(很久以前给出的),我也有了改变字体大小的想法-然后阅读你的评论。。。如果两个人独立地提出了相同的想法,那就必须是好的;)嗨,陆-我真的爱你,但这真的是个坏主意。对不起,伙计!以本地化为例。。。这会把事情搞得一团糟。这对可访问性来说真是个坏主意。如果您使用此选项,请确保将辅助功能标签设置为real text.beautiful-您不会在此处使用IBDesignables吗?但此问题是关于字母间距,而不是行距+1。真棒的回答。如果文本必须保持居中,则对除最后一个字符以外的所有字符应用紧排,即将
NSMakeRange(0,attributedString.length)
更改为
NSMakeRange(0,attributedString.length-1)
。可以更改字符间距吗?@Priyal,其中有一个1.15的间距值。。。如果你想要更多,就把它改大一点spacing@budidino正如我可以从示例中推断的,您增加了单词之间的间距,但我想更改字符间距,即We和user或used和to之间的间距。。。。但我想管理We的W和e之间的间距,user的u、s、e和r之间的间距。可能吗?@budidino谢谢!这等同于减少横向间距吗?回答得很好!少量添加:您可以将if子句更改为
if let textString=text,textString.length>0
,以便在字符串为“”(空)时捕获超出范围的索引。如果不指定范围,则居中对齐和右对齐的文本将看起来不明显,因为在最后一个字符后将添加空格。我可能完全错了:)它工作得很好。似乎我的代码中缺少了一部分。抱歉,这不支持完全完美的定制方式。我还为UILabel和UI添加了相同的代码