在 Interface Builder 中更改 UILabel 上的字符间距
Posted
技术标签:
【中文标题】在 Interface Builder 中更改 UILabel 上的字符间距【英文标题】:Change character spacing on UILabel within Interface Builder 【发布时间】:2014-12-17 22:18:24 【问题描述】:是否可以使用 Interface Builder 更改 UILabel 文本上的字符间距(轨道)?如果没有,有没有办法在已经使用属性文本创建的现有 UILabel 上以编程方式执行此操作?
【问题讨论】:
我 99% 确定 Xcode 6 不支持这个。 @Drux 我 99% 确定 Xcode 6 可以做 IBDesignables 【参考方案1】:我知道这不是一个 Interface Builder 解决方案,但您可以创建一个 UILabel
扩展,然后为您想要的任何 UILabel
添加间距:
extension UILabel
func addCharacterSpacing(kernValue: Double = 1.15)
guard let text = text, !text.isEmpty else return
let string = NSMutableAttributedString(string: text)
string.addAttribute(NSAttributedString.Key.kern, value: kernValue, range: NSRange(location: 0, length: string.length - 1))
attributedText = string
考虑将默认的 kernValue
从 1.15
更改为更适合您的设计的内容。
实现always时,在设置文本值后添加字符间距:
myLabel.text = "We used to be so close"
myLabel.addCharacterSpacing()
如果您打算在应用中的不同位置设置不同的间距,您可以覆盖默认的 kern 值:
myLabelWithSpecialNeeds.addCharacterSpacing(kernValue: 1.3)
此解决方案会覆盖您在 UILabel
的 attributedText
上可能拥有的任何其他属性。
【讨论】:
是否可以更改字符间距? @Priyal,里面有一个 1.15 的间距值......如果你想要更多的间距,只需将其更改为更大的数字 @budidino 我可以从示例中推断出您增加了单词之间的间距,但我想更改字符间距,即。在 We & user 或 used & to.... 之间,但我想管理 We 的 'W' 和 'e'、用户的 'u'、's'、'e' 和 'r' 之间的间距。有可能吗? @budidino 谢谢!是不是相当于缩小横向间距? 非常好的答案!小补充:当字符串为“”(空)时,您可以将 if 子句更改为if let textString = text, textString.length > 0
以catch index out of bounds。【参考方案2】:
暂时使用它来获取现有的属性文本并修改以添加字符间距:
let attributedString = discoveryTitle.attributedText as NSMutableAttributedString
attributedString.addAttribute(NSKernAttributeName, value: 1.0, range: NSMakeRange(0, attributedString.length))
discoveryTitle.attributedText = attributedString
斯威夫特 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 中有效。
【讨论】:
+1。很棒的答案。如果您的文本必须保持居中,则将字距应用于除最后一个字符之外的所有字符,即将NSMakeRange(0, attributedString.length)
更改为NSMakeRange(0, attributedString.length - 1)
。 Source
@paulvs 是正确的。您还需要验证空字符串以避免崩溃。只需添加max(0, attributedString.length - 1)
即可。【参考方案3】:
对于完全静态的文本,例如视图的标题或特别是 launchScreen,您可以插入占用很小宽度的字母(例如 'l ' 字符)与0 opacity
。或者将其颜色设置为与背景相同。
我知道,这不是最漂亮的解决方案,但它是唯一无需编写任何代码即可工作并完成工作的解决方案 - 直到您可以通过在 Xcode 中指定属性来完成。
编辑/附加想法:要使您的间距更加可变,您可以更改填充字符的字体大小。 (感谢@mohamede1945 的想法)
【讨论】:
很棒的解决方案! :) 您甚至可以使用“|”的字体大小来控制宽度特点。您所需要的只是创建一个并复制/粘贴它:) @mohamede1945 好主意,在我真正阅读您的评论并再次通读我的答案之前(已经给出了很长一段时间)我也想到了可能更改字体大小的想法 - 然后阅读您的评论...如果两个人独立提出相同的想法,那一定很好;) 嗨 Luk - 我真的爱你,但这确实是个坏主意。对不起,伙计! 以本地化为例……它会搞砸的 这对于可访问性来说是一个非常糟糕的主意。如果您使用它,请务必将可访问性标签设置为真实文本。【参考方案4】: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
【讨论】:
完美运行。似乎我在我的代码中遗漏了一部分。对不起 这个不支持自定义字体 完全完美的方式。我还为 UILabel 和 UIButton 添加了相同的代码,它们也可以工作。只需从 UIButton 的 titleLabel.text 和 titleLabel.attributedText 获取文本 很好的解决方案,在更高版本的 Xcode 中更新了一些代码更新,但 Xcode 会为您处理所有修复。谢谢!【参考方案5】:Swift 5 及更高版本
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
【讨论】:
@craft 他在没有默认值之前编辑了他的答案。我也会编辑我的,谢谢。【参考方案6】:试试这个!!
创建 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;
并设置运行时属性
注意这实际上是 行距(也称为 leading .. 在过去(数字化之前)你会说线之间的铅(金属)以增加线之间的间隙。对于字母之间的间距,这称为kerning ..这是如何进行kerning https://***.com/a/21141156/294884
【讨论】:
漂亮 - 你不会在这里使用 IBDesignables 吗? 但这个问题是关于字母间距,而不是行间距【参考方案7】:为什么你们都在定义 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)
【讨论】:
如果您不指定范围,则居中和右对齐的文本将看起来不正确,因为在最后一个字符之后会添加间距。不过我可能完全错了:)【参考方案8】:SWIFT 4 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
【讨论】:
【参考方案9】:这是一个不会覆盖现有文本属性的 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
【讨论】:
【参考方案10】:您可以使用以下 Swift 4 UILabel 扩展,该扩展同时考虑现有的属性文本和纯文本,以免覆盖现有设置:
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
【讨论】:
【参考方案11】:这是我的字母间距代码。创建自定义标签类并从情节提要中设置字母间距。斯威夫特 5。
import UIKit
class SpacingLabel: UILabel
@IBInspectable
var letterSpacing: Double = 0
override public var text: String?
didSet
self.addCharacterSpacing(letterSpacing)
func addCharacterSpacing(_ kernValue: Double)
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
【讨论】:
请注意,您必须从代码中调用 label.text = "some text" 才能使其工作:))【参考方案12】:试试这个。它将添加您指定的字符间距,您可以设置简单文本或属性文本。
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
【讨论】:
【参考方案13】:编程方法。(试试这个,它应该适合你) 注意:我在 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
【讨论】:
【参考方案14】:斯威夫特 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
【讨论】:
这与@budidino 的回答有何不同? @craft 'NSAttributedStringKey' 已重命名为 'NSAttributedString.Key'以上是关于在 Interface Builder 中更改 UILabel 上的字符间距的主要内容,如果未能解决你的问题,请参考以下文章
通过 Interface Builder 更改 UIView 属性
在 Interface Builder 中使用 Auto Layout 更改方向
如何在 Interface Builder 中更改 UIButton 的背景图像并保留其形状?
为啥在 Interface Builder 中更改字体大小会阻止 UILabel 调整大小以适应内容?