大胆&单个 UILabel 中的非粗体文本? [英] Bold & Non-Bold Text In A Single UILabel?

查看:31
本文介绍了大胆&单个 UILabel 中的非粗体文本?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 uiLabel 中同时包含粗体和非粗体文本?

How would it be possible to include both bold and non-bold text in a uiLabel?

我宁愿不使用 UIWebView .. 我也读过这可能使用 NSAttributedString 但我不知道如何使用它.有什么想法吗?

I'd rather not use a UIWebView.. I've also read this may be possible using NSAttributedString but I have no idea how to use that. Any ideas?

Apple 在他们的几个应用程序中实现了这一点;示例截图:

Apple achieves this in several of their apps; Examples Screenshot:

谢谢!- 多姆

推荐答案

更新

在 Swift 中,除了语法更短之外,我们不必处理 iOS5 的旧东西,所以一切都变得非常简单:

Update

In Swift we don't have to deal with iOS5 old stuff besides syntax is shorter so everything becomes really simple:

Swift 5

func attributedString(from string: String, nonBoldRange: NSRange?) -> NSAttributedString {
    let fontSize = UIFont.systemFontSize
    let attrs = [
        NSAttributedString.Key.font: UIFont.boldSystemFont(ofSize: fontSize),
        NSAttributedString.Key.foregroundColor: UIColor.black
    ]
    let nonBoldAttribute = [
        NSAttributedString.Key.font: UIFont.systemFont(ofSize: fontSize),
    ]
    let attrStr = NSMutableAttributedString(string: string, attributes: attrs)
    if let range = nonBoldRange {
        attrStr.setAttributes(nonBoldAttribute, range: range)
    }
    return attrStr
}

Swift 3

func attributedString(from string: String, nonBoldRange: NSRange?) -> NSAttributedString {
    let fontSize = UIFont.systemFontSize
    let attrs = [
        NSFontAttributeName: UIFont.boldSystemFont(ofSize: fontSize),
        NSForegroundColorAttributeName: UIColor.black
    ]
    let nonBoldAttribute = [
        NSFontAttributeName: UIFont.systemFont(ofSize: fontSize),
    ]
    let attrStr = NSMutableAttributedString(string: string, attributes: attrs)
    if let range = nonBoldRange {
        attrStr.setAttributes(nonBoldAttribute, range: range)
    }
    return attrStr
}

用法:

let targetString = "Updated 2012/10/14 21:59 PM"
let range = NSMakeRange(7, 12)

let label = UILabel(frame: CGRect(x:0, y:0, width:350, height:44))
label.backgroundColor = UIColor.white
label.attributedText = attributedString(from: targetString, nonBoldRange: range)
label.sizeToFit()

奖励:国际化

有些人评论了国际化.我个人认为这超出了这个问题的范围,但出于教学目的,这就是我的做法

Bonus: Internationalisation

Some people commented about internationalisation. I personally think this is out of scope of this question but for instructional purposes this is how I would do it

// Date we want to show
let date = Date()

// Create the string.
// I don't set the locale because the default locale of the formatter is `NSLocale.current` so it's good for internationalisation :p
let formatter = DateFormatter()
formatter.dateStyle = .medium
formatter.timeStyle = .short
let targetString = String(format: NSLocalizedString("Update %@", comment: "Updated string format"),
                          formatter.string(from: date))

// Find the range of the non-bold part
formatter.timeStyle = .none
let nonBoldRange = targetString.range(of: formatter.string(from: date))

// Convert Range<Int> into NSRange
let nonBoldNSRange: NSRange? = nonBoldRange == nil ?
    nil :
    NSMakeRange(targetString.distance(from: targetString.startIndex, to: nonBoldRange!.lowerBound),
                targetString.distance(from: nonBoldRange!.lowerBound, to: nonBoldRange!.upperBound))

// Now just build the attributed string as before :)
label.attributedText = attributedString(from: targetString,
                                        nonBoldRange: nonBoldNSRange)

结果(假设英语和日语 Localizable.strings 可用)

Result (Assuming English and Japanese Localizable.strings are available)

在 iOS6 UILabelUIButtonUITextViewUITextField 中,支持属性字符串,这意味着我们不需要创建 CATextLayer 作为属性字符串的接收者.此外,为了制作属性字符串,我们不再需要使用 CoreText :) 我们在 obj-c Foundation.framework 中有新类,例如 NSParagraphStyle 和其他常量,它们将使我们的生活更轻松.耶!

In iOS6 UILabel, UIButton, UITextView, UITextField, support attributed strings which means we don't need to create CATextLayers as our recipient for attributed strings. Furthermore to make the attributed string we don't need to play with CoreText anymore :) We have new classes in obj-c Foundation.framework like NSParagraphStyle and other constants that will make our life easier. Yay!

所以,如果我们有这个字符串:

So, if we have this string:

NSString *text = @"Updated: 2012/10/14 21:59"

我们只需要创建属性字符串:

We only need to create the attributed string:

if ([_label respondsToSelector:@selector(setAttributedText:)])
{
    // iOS6 and above : Use NSAttributedStrings

    // Create the attributes
    const CGFloat fontSize = 13;
    NSDictionary *attrs = @{
        NSFontAttributeName:[UIFont boldSystemFontOfSize:fontSize],
        NSForegroundColorAttributeName:[UIColor whiteColor]
    };
    NSDictionary *subAttrs = @{
        NSFontAttributeName:[UIFont systemFontOfSize:fontSize]
    };

    // Range of " 2012/10/14 " is (8,12). Ideally it shouldn't be hardcoded
    // This example is about attributed strings in one label
    // not about internationalisation, so we keep it simple :)
    // For internationalisation example see above code in swift
    const NSRange range = NSMakeRange(8,12);

    // Create the attributed string (text + attributes)
    NSMutableAttributedString *attributedText =
      [[NSMutableAttributedString alloc] initWithString:text
                                             attributes:attrs];
    [attributedText setAttributes:subAttrs range:range];

    // Set it in our UILabel and we are done!
    [_label setAttributedText:attributedText];
} else {
    // iOS5 and below
    // Here we have some options too. The first one is to do something
    // less fancy and show it just as plain text without attributes.
    // The second is to use CoreText and get similar results with a bit
    // more of code. Interested people please look down the old answer.

    // Now I am just being lazy so :p
    [_label setText:text];
}

有几个很好的介绍性博客文章这里来自侵入代码的人用更多示例解释 NSAttributedString 的用法,查找 iOS 6 的 NSAttributedString 简介"iOS 使用 Interface Builder 的属性字符串":)

There is a couple of good introductory blog posts here from guys at invasivecode that explain with more examples uses of NSAttributedString, look for "Introduction to NSAttributedString for iOS 6" and "Attributed strings for iOS using Interface Builder" :)

PS:上面的代码应该可以工作,但它是大脑编译的.我希望它足够了:)

PS: Above code it should work but it was brain-compiled. I hope it is enough :)

使用带有 NSAttributedString 的 CATextLayer !比 2 个 UILabels 更轻、更简单.(iOS 3.2 及以上)

Use a CATextLayer with an NSAttributedString ! much lighter and simpler than 2 UILabels. (iOS 3.2 and above)

示例.

不要忘记添加 QuartzCore 框架(CALayers 需要)和 CoreText(属性字符串需要)

Don't forget to add QuartzCore framework (needed for CALayers), and CoreText (needed for the attributed string.)

#import <QuartzCore/QuartzCore.h>
#import <CoreText/CoreText.h>

下面的示例将向导航控制器的工具栏添加一个子层.à la Mail.app 在 iPhone 中.:)

Below example will add a sublayer to the toolbar of the navigation controller. à la Mail.app in the iPhone. :)

- (void)setRefreshDate:(NSDate *)aDate
{
    [aDate retain];
    [refreshDate release];
    refreshDate = aDate;

    if (refreshDate) {

        /* Create the text for the text layer*/    
        NSDateFormatter *df = [[NSDateFormatter alloc] init];
        [df setDateFormat:@"MM/dd/yyyy hh:mm"];

        NSString *dateString = [df stringFromDate:refreshDate];
        NSString *prefix = NSLocalizedString(@"Updated", nil);
        NSString *text = [NSString stringWithFormat:@"%@: %@",prefix, dateString];
        [df release];

        /* Create the text layer on demand */
        if (!_textLayer) {
            _textLayer = [[CATextLayer alloc] init];
            //_textLayer.font = [UIFont boldSystemFontOfSize:13].fontName; // not needed since `string` property will be an NSAttributedString
            _textLayer.backgroundColor = [UIColor clearColor].CGColor;
            _textLayer.wrapped = NO;
            CALayer *layer = self.navigationController.toolbar.layer; //self is a view controller contained by a navigation controller
            _textLayer.frame = CGRectMake((layer.bounds.size.width-180)/2 + 10, (layer.bounds.size.height-30)/2 + 10, 180, 30);
            _textLayer.contentsScale = [[UIScreen mainScreen] scale]; // looks nice in retina displays too :)
            _textLayer.alignmentMode = kCAAlignmentCenter;
            [layer addSublayer:_textLayer];
        }

        /* Create the attributes (for the attributed string) */
        CGFloat fontSize = 13;
        UIFont *boldFont = [UIFont boldSystemFontOfSize:fontSize];
        CTFontRef ctBoldFont = CTFontCreateWithName((CFStringRef)boldFont.fontName, boldFont.pointSize, NULL);
        UIFont *font = [UIFont systemFontOfSize:13];
        CTFontRef ctFont = CTFontCreateWithName((CFStringRef)font.fontName, font.pointSize, NULL);
        CGColorRef cgColor = [UIColor whiteColor].CGColor;
        NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
                                    (id)ctBoldFont, (id)kCTFontAttributeName,
                                    cgColor, (id)kCTForegroundColorAttributeName, nil];
        CFRelease(ctBoldFont);
        NSDictionary *subAttributes = [NSDictionary dictionaryWithObjectsAndKeys:(id)ctFont, (id)kCTFontAttributeName, nil];
        CFRelease(ctFont);

        /* Create the attributed string (text + attributes) */
        NSMutableAttributedString *attrStr = [[NSMutableAttributedString alloc] initWithString:text attributes:attributes];
        [attrStr addAttributes:subAttributes range:NSMakeRange(prefix.length, 12)]; //12 is the length of " MM/dd/yyyy/ "

        /* Set the attributes string in the text layer :) */
        _textLayer.string = attrStr;
        [attrStr release];

        _textLayer.opacity = 1.0;
    } else {
        _textLayer.opacity = 0.0;
        _textLayer.string = nil;
    }
}

在这个例子中,我只有两种不同类型的字体(粗体和普通),但你也可以有不同的字体大小、不同的颜色、斜体、下划线等.看看 NSAttributedString/NSMutableAttributedStringCoreText 属性字符串键.

In this example I only have two different types of font (bold and normal) but you could also have different font size, different color, italics, underlined, etc. Take a look at NSAttributedString / NSMutableAttributedString and CoreText attributes string keys.

希望能帮到你

这篇关于大胆&amp;单个 UILabel 中的非粗体文本?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆