NSAttributedString如何在不改变字号的情况下更改粗体样式?

19

我正在研究iOS上的NSAttributedString。 我有一个模型,它将人的名字和姓氏作为NSAttributesString返回。(我不知道在模型中处理带属性的字符串是否是一个好主意!?)我想要将名字以常规字体打印,而将姓氏以粗体字打印。但我不想设置文本大小。到目前为止,我找到的所有内容都是这样的:

- (NSAttributedString*)attributedName {
    NSMutableAttributedString* name = [[NSMutableAttributedString alloc] initWithString:self.name];
    [name setAttributes:@{NSFontAttributeName : [UIFont boldSystemFontOfSize:[UIFont systemFontSize]]} range:[self.name rangeOfString:self.lastname]];
    return name;
}

然而,这样做会覆盖掉姓氏的字体大小,在UITableViewCell中会出现非常诡异的情况,因为名字将以标签单元格标签的正常文本大小打印,而姓氏则会非常小。

有没有办法实现我想要的效果?

感谢您的帮助!

6个回答

7

通过使用负值的StrokeWidth属性,您可以在不更改其它属性的情况下使字符串加粗。

Objective-C:

[name setAttributes:@{NSStrokeWidthAttributeName : @-3.0} range:NSRangeFromString(name.string)];

Swift:

name.setAttributes([.strokeWidth: NSNumber(value: -3.0)], range: NSRangeFromString(name.string))

但是,当您在TextEdit中选择某些文本并选择“bold”时,这是否是Cocoa定义的“bold”?它看起来会一样吗?那么,“-3.0”值是什么意思?它是否会使文本在水平方向上模糊3个点? - Motti Shneor
在我看来它们都是一样的... 文字很清晰,没有模糊 - 你可以试着看看。 - Yonat

7
这里有一个 Swift 扩展,可以使文本加粗,同时保留当前字体属性(以及文字大小)。
public extension UILabel {

    /// Makes the text bold.
    public func makeBold() {
        //get the UILabel's fontDescriptor
        let desc = self.font.fontDescriptor.withSymbolicTraits(.traitBold)
        //Setting size to '0.0' will preserve the textSize
        self.font = UIFont(descriptor: desc, size: 0.0)
    }

}

4

使用此问题中的技术:

UIFontDescriptor *fontDescriptor = [UIFontDescriptor preferredFontDescriptorWithTextStyle:UIFontTextStyleBody];
uint32_t existingTraitsWithNewTrait = UIFontDescriptorTraitBold;
    fontDescriptor = [fontDescriptor fontDescriptorWithSymbolicTraits:existingTraitsWithNewTrait];
UIFont *updatedFont = [UIFont fontWithDescriptor:fontDescriptor size:0.0];
NSDictionary *attribs =  @{NSFontAttributeName : updatedFont};
[mutableAttrString setAttributes:attribs range:result.range];

在MacOS中,preferredFontDescriptorWithTextStyle仅适用于MacOS 11及更高版本 - 因此,我们不能依赖它来支持需要支持MacOS 10.13及以上版本的应用程序。那么有什么替代方案呢?那些“系统样式”现在在Interface-Builder中相当古老了 - 如何在没有新API的情况下以编程方式访问它们? - Motti Shneor

2

如果你只想加粗字符串标签中的第二个单词,例如用于姓名标签,同时使用默认的iOS系统字体,如标题或标题等

let s = "\(client.givenName) \(client.surname)" as NSString

let myAttribute = [ NSFontAttributeName: UIFont.preferredFontForTextStyle(UIFontTextStyleTitle1) ]
let myString = NSMutableAttributedString(string: "\(s)", attributes: myAttribute )

let myRange = s.rangeOfString(client.surname)
let desc = UIFont.preferredFontForTextStyle(UIFontTextStyleTitle1).fontDescriptor().fontDescriptorWithSymbolicTraits(.TraitBold)
let new = UIFont(descriptor: desc, size: 0.0)

myString.addAttribute(NSFontAttributeName, value: new, range: myRange)

nameLabel.attributedText = myString

你能否分享一个 Obj-C 版本的吗? - Jason McDermott
你知道MacOS是否有这样的API吗?NSFont和相关类会提供这样的功能吗? - Motti Shneor

2

您尝试将大小设置为0.0了吗?


2
从单元格代码中进行上述调用,但通过从单元格的textLabel获取字体大小来传递所需的字体大小。请注意保留HTML标签。

我尝试过了,但是一个新的、干净的初始化的UITableViewCell在textLabel上返回pointSize 0.0f(可能是字体或甚至是textLabel为空)!你有什么办法解决这个问题吗? - Michael Ochs
3
如果您实现了 tableView:willDisplayCellAtIndexPath: 委托方法,字体应该在此设置,并且您可以在此更新字体。 - rmaddy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接