【问题标题】:Center two fonts with different different sizes vertically in an NSAttributedString在 NSAttributedString 中垂直居中两种不同大小的字体
【发布时间】:2013-10-21 06:12:44
【问题描述】:

我使用NSAttributedString 生成具有两种不同大小的字符串。默认情况下,它的底部对齐方式如下所示:

但我想将其垂直居中,如下所示:

需要明确的是,这是一个单一的属性字符串,而不是两个或更多。这是一个描述我的问题的简化示例,我真正想做的事情更复杂。

【问题讨论】:

  • 您是否考虑过为此使用两个单独的视图?因此,例如有两个UILabels 并在调整它们的大小后,将它们的框架居中对齐。对我来说,这似乎比弄乱字体大小和基线偏移要干净得多。

标签: ios nsattributedstring


【解决方案1】:

我想说最简单的方法就是操作相关文本的 NSBaselineOffsetAttributeName 属性:

NSBaselineOffsetAttributeName

该属性的值是一个 NSNumber 对象,其中包含一个浮点值,表示字符相对于基线的偏移量,以磅为单位。默认值为 0。

要居中,您需要将大文本的高度与较小文本的高度之间的差值减半,然后将其用作基线调整。

【讨论】:

  • 现在是NSAttributedStringKey.baselineOffset
  • 现在是NSAttributedString.Key.baselineOffset
【解决方案2】:

这是一个使用 NSBaselineOffsetAttributeName 垂直对齐较小文本的工作示例。

NSString *bigString   = @"BIG";
NSString *smallString = @"Small String";
NSString *fullString = [NSString stringWithFormat:@"%@ %@", bigString, smallString];

NSMutableAttributedString *string = [[NSMutableAttributedString alloc] initWithString:fullString];

NSRange bigStringRange = NSMakeRange(0, bigString.length);
NSRange smallStringRange = NSMakeRange(bigStringRange.length, smallString.length);

[string beginEditing];


//Set big string font and size
[string addAttribute:NSFontAttributeName
               value:[UIFont systemFontOfSize:28.0]
               range:bigStringRange];

//set small string font and size
[string addAttribute:NSFontAttributeName
               value:[UIFont systemFontOfSize:18.0]
               range:smallStringRange];

//Set small string baseline offset
[string addAttribute:NSBaselineOffsetAttributeName
               value:[NSNumber numberWithFloat:3.0]  //adjust this number till text appears to be centered
               range:smallStringRange];

[string endEditing];

【讨论】:

  • 抱歉,这更像是一次尝试和错误的破解,而不是真正的解决方案。但是,如果结合一些即时数学,这可能是一个解决方案。
  • 嗯,它按原样工作。你只需要找出不应该超过几次尝试的基线值。
  • 当然,即使您获取所有字体指标并做正确的事情,一旦您在不同的字符中添加单个字符,您可能必须重新计算字符串中每个范围的基线偏移量大小....
  • 永远不要相信一个不会偶尔使用 hack 的程序员……
【解决方案3】:

YasT's answer 在 Swift 中:

斯威夫特 4

let bigString = "BIG"
let smallString = "Small String"
let fullString = "\(bigString) \(smallString)"
let string = NSMutableAttributedString(string: fullString)

let bigStringRange = NSRange(location: 0, length: bigString.utf16.count)
let smallStringRange = NSRange(location: bigStringRange.length + 1, length: smallString.utf16.count)

let bigStringFontSize: CGFloat = 28
let smallStringFontSize: CGFloat = 18

string.beginEditing()

string.addAttribute(.font, value: UIFont.systemFont(ofSize: bigStringFontSize), range: bigStringRange)
string.addAttribute(.font, value: UIFont.systemFont(ofSize: smallStringFontSize), range: smallStringRange)
string.addAttribute(.baselineOffset, value: (bigStringFontSize - smallStringFontSize) / 2, range: smallStringRange)

string.endEditing()

斯威夫特 3

let bigString = "BIG"
let smallString = "Small String"
let fullString = "\(bigString) \(smallString)"
let string = NSMutableAttributedString(string: fullString)

let bigStringRange = NSRange(location: 0, length: bigString.utf16.count)
let smallStringRange = NSRange(location: bigStringRange.length + 1, length: smallString.utf16.count)

let bigStringFontSize: CGFloat = 28
let smallStringFontSize: CGFloat = 18

string.beginEditing()

string.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: bigStringFontSize), range: bigStringRange)
string.addAttribute(NSFontAttributeName, value: UIFont.systemFont(ofSize: smallStringFontSize), range: smallStringRange)
string.addAttribute(NSBaselineOffsetAttributeName, value: (bigStringFontSize - smallStringFontSize) / 2, range: smallStringRange)

string.endEditing()

【讨论】:

    【解决方案4】:

    更好的解决方案是从字体排版计算 NSBaselineOffsetAttributeName(短文https://www.raizlabs.com/dev/2015/08/advanced-ios-typography/

    为属性字符串的第二部分设置属性。

    secondPartAttributes[NSBaselineOffsetAttributeName] = @((firstFont.xHeight - secondFont.xHeight)/2);
    

    【讨论】:

    • 非常好的article 你在那里引用了!更可爱的是NSAttributedString 扩展,它从给定对象的属性中提取最大的fontSize,并使用您的示例指示的较小字体调整所有其他范围的基线,并返回NSMutableAttributedString。我希望很快有时间做这样的事情。
    • 你应该使用 capHeight,而不是 xHeight。
    猜你喜欢
    • 2013-08-24
    • 2020-09-19
    • 2018-05-29
    • 2014-07-24
    • 2018-04-30
    • 1970-01-01
    • 1970-01-01
    • 2015-08-07
    • 2016-06-15
    相关资源
    最近更新 更多