ios 单个 UILabel 中的粗体和非粗体文本?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/3586871/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Bold & Non-Bold Text In A Single UILabel?
提问by DomMaiocchi
How would it be possible to include both bold and non-bold text in a uiLabel?
如何在 uiLabel 中同时包含粗体和非粗体文本?
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?
我宁愿不使用 UIWebView ..我也读过这可能使用 NSAttributedString 但我不知道如何使用它。有任何想法吗?
Apple achieves this in several of their apps;
Examples Screenshot:
苹果在他们的几个应用程序中实现了这一点;示例截图:
Thanks! - Dom
谢谢!- 多姆
回答by nacho4d
Update
更新
In Swift we don't have to deal with iOS5 old stuff besides syntax is shorter so everything becomes really simple:
在 Swift 中,除了语法更短之外,我们不必处理 iOS5 的旧东西,所以一切都变得非常简单:
Swift 5
斯威夫特 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
斯威夫特 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
}
Usage:
用法:
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)
Result (Assuming English and Japanese Localizable.strings are available)
结果(假设英语和日语 Localizable.strings 可用)
Previous answer for iOS6 and later (Objective-C still works):
iOS6 及更高版本的先前答案(Objective-C 仍然有效):
In iOS6 UILabel
, UIButton
, UITextView
, UITextField
, support attributed strings which means we don't need to create CATextLayer
s 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!
在 iOS6 中UILabel
,UIButton
, UITextView
, UITextField
, 支持属性字符串,这意味着我们不需要创建CATextLayer
s 作为属性字符串的接收者。此外,为了制作属性字符串,我们不再需要使用 CoreText :) 我们在 obj-c Foundation.framework 中添加了新类NSParagraphStyle
和其他常量,这将使我们的生活更轻松。好极了!
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];
}
There is a couple of good introductory blog posts herefrom guys at invasivecodethat explain with more examples uses of NSAttributedString
, look for "Introduction to NSAttributedString for iOS 6"and "Attributed strings for iOS using Interface Builder":)
这里有一些很好的介绍性博客文章,来自侵入代码的人,解释了更多示例用法NSAttributedString
,查找“iOS 6 的 NSAttributedString 简介”和“使用界面生成器的 iOS 属性字符串”:)
PS: Above code it should work but it was brain-compiled. I hope it is enough :)
PS:上面的代码应该可以工作,但它是大脑编译的。我希望它足够了:)
Old Answer for iOS5 and below
iOS5 及以下的旧答案
Use a CATextLayerwith an NSAttributedString ! much lighter and simpler than 2 UILabels. (iOS 3.2 and above)
使用带有NSAttributedString的 CATextLayer !比 2 个 UILabels 更轻、更简单。(iOS 3.2 及以上)
Example.
例子。
Don't forget to add QuartzCore framework (needed for CALayers), and CoreText (needed for the attributed string.)
不要忘记添加 QuartzCore 框架(CALayers 需要)和 CoreText(属性字符串需要)。
#import <QuartzCore/QuartzCore.h>
#import <CoreText/CoreText.h>
Below example will add a sublayer to the toolbar of the navigation controller. à la Mail.app in the iPhone. :)
下面的示例将向导航控制器的工具栏添加一个子层。à la Mail.app 在 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;
}
}
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/ NSMutableAttributedStringand CoreText attributes string keys.
在这个例子中,我只有两种不同类型的字体(粗体和普通),但你也可以有不同的字体大小、不同的颜色、斜体、下划线等。看看NSAttributedString/ NSMutableAttributedString和CoreText 属性字符串键。
Hope it helps
希望能帮助到你
回答by bbrame
Try a category on UILabel:
在 UILabel 上尝试一个类别:
Here's how it's used:
这是它的使用方法:
myLabel.text = @"Updated: 2012/10/14 21:59 PM";
[myLabel boldSubstring: @"Updated:"];
[myLabel boldSubstring: @"21:59 PM"];
And here's the category
这是类别
UILabel+Boldify.h
UILabel+加粗.h
- (void) boldSubstring: (NSString*) substring;
- (void) boldRange: (NSRange) range;
UILabel+Boldify.m
UILabel+Boldify.m
- (void) boldRange: (NSRange) range {
if (![self respondsToSelector:@selector(setAttributedText:)]) {
return;
}
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range];
self.attributedText = attributedText;
}
- (void) boldSubstring: (NSString*) substring {
NSRange range = [self.text rangeOfString:substring];
[self boldRange:range];
}
Note that this will only work in iOS 6 and later. It will simply be ignored in iOS 5 and earlier.
请注意,这仅适用于 iOS 6 及更高版本。在 iOS 5 及更早版本中它会被忽略。
回答by Anton Gaenko
That's easy to do in Interface Builder:
这在Interface Builder 中很容易做到:
1) make UILabelAttributedin Attributes Inspector
1)在Attributes Inspector 中设置UILabel Attributed
2) select part of phrase you want to make bold
2) 选择要加粗的部分短语
3) change its font (or bold typeface of the same font) in font selector
3)在字体选择器中更改其字体(或相同字体的粗体)
That's all!
就这样!
回答by Crazy Yoghurt
There's category based on bbrame's category. It works similar, but allows you boldify same UILabel
multiple times with cumulative results.
有基于 bbrame 类别的类别。它的工作原理类似,但允许您UILabel
使用累积结果多次加粗。
UILabel+Boldify.h
UILabel+加粗.h
@interface UILabel (Boldify)
- (void) boldSubstring: (NSString*) substring;
- (void) boldRange: (NSRange) range;
@end
UILabel+Boldify.m
UILabel+Boldify.m
@implementation UILabel (Boldify)
- (void)boldRange:(NSRange)range {
if (![self respondsToSelector:@selector(setAttributedText:)]) {
return;
}
NSMutableAttributedString *attributedText;
if (!self.attributedText) {
attributedText = [[NSMutableAttributedString alloc] initWithString:self.text];
} else {
attributedText = [[NSMutableAttributedString alloc] initWithAttributedString:self.attributedText];
}
[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:self.font.pointSize]} range:range];
self.attributedText = attributedText;
}
- (void)boldSubstring:(NSString*)substring {
NSRange range = [self.text rangeOfString:substring];
[self boldRange:range];
}
@end
With this corrections you may use it multiple times, eg:
通过此更正,您可以多次使用它,例如:
myLabel.text = @"Updated: 2012/10/14 21:59 PM";
[myLabel boldSubstring: @"Updated:"];
[myLabel boldSubstring: @"21:59 PM"];
will result with: "Updated:2012/10/14 21:59 PM".
将导致:“更新:2012/10/14 21:59 PM”。
回答by Prajeet Shrestha
It worked for me:
它对我有用:
CGFloat boldTextFontSize = 17.0f;
myLabel.text = [NSString stringWithFormat:@"%@ 2012/10/14 %@",@"Updated:",@"21:59 PM"];
NSRange range1 = [myLabel.text rangeOfString:@"Updated:"];
NSRange range2 = [myLabel.text rangeOfString:@"21:59 PM"];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:myLabel.text];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]}
range:range1];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont boldSystemFontOfSize:boldTextFontSize]}
range:range2];
myLabel.attributedText = attributedText;
For Swift version: See Here
对于 Swift 版本:请参阅此处
回答by Artem Mostyaev
I've adopted Crazy Yoghurt's answer to swift's extensions.
我采用了 Crazy Yoghurt 对 swift 扩展的回答。
extension UILabel {
func boldRange(_ range: Range<String.Index>) {
if let text = self.attributedText {
let attr = NSMutableAttributedString(attributedString: text)
let start = text.string.characters.distance(from: text.string.startIndex, to: range.lowerBound)
let length = text.string.characters.distance(from: range.lowerBound, to: range.upperBound)
attr.addAttributes([NSFontAttributeName: UIFont.boldSystemFont(ofSize: self.font.pointSize)], range: NSMakeRange(start, length))
self.attributedText = attr
}
}
func boldSubstring(_ substr: String) {
if let text = self.attributedText {
var range = text.string.range(of: substr)
let attr = NSMutableAttributedString(attributedString: text)
while range != nil {
let start = text.string.characters.distance(from: text.string.startIndex, to: range!.lowerBound)
let length = text.string.characters.distance(from: range!.lowerBound, to: range!.upperBound)
var nsRange = NSMakeRange(start, length)
let font = attr.attribute(NSFontAttributeName, at: start, effectiveRange: &nsRange) as! UIFont
if !font.fontDescriptor.symbolicTraits.contains(.traitBold) {
break
}
range = text.string.range(of: substr, options: NSString.CompareOptions.literal, range: range!.upperBound..<text.string.endIndex, locale: nil)
}
if let r = range {
boldRange(r)
}
}
}
}
May be there is not good conversion between Range and NSRange, but I didn't found something better.
可能 Range 和 NSRange 之间没有很好的转换,但我没有找到更好的东西。
回答by mattt
Check out TTTAttributedLabel. It's a drop-in replacement for UILabel that allows you to have mixed font and colors in a single label by setting an NSAttributedString as the text for that label.
查看TTTAttributedLabel。它是 UILabel 的替代品,通过将 NSAttributedString 设置为该标签的文本,您可以在单个标签中混合字体和颜色。
回答by x4h1d
In this case you could try,
在这种情况下,你可以尝试,
UILabel *displayLabel = [[UILabel alloc] initWithFrame:/*label frame*/];
displayLabel.font = [UIFont boldSystemFontOfSize:/*bold font size*/];
NSMutableAttributedString *notifyingStr = [[NSMutableAttributedString alloc] initWithString:@"Updated: 2012/10/14 21:59 PM"];
[notifyingStr beginEditing];
[notifyingStr addAttribute:NSFontAttributeName
value:[UIFont systemFontOfSize:/*normal font size*/]
range:NSMakeRange(8,10)/*range of normal string, e.g. 2012/10/14*/];
[notifyingStr endEditing];
displayLabel.attributedText = notifyingStr; // or [displayLabel setAttributedText: notifyingStr];
回答by Ankit Goyal
To make text bold as well as underline in a UILabel. Just add the following lines in your code.
在 UILabel 中使文本加粗并加下划线。只需在您的代码中添加以下几行即可。
NSRange range1 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_terms", @"")];
NSRange range2 = [lblTermsAndCondition.text rangeOfString:NSLocalizedString(@"bold_policy", @"")];
NSMutableAttributedString *attributedText = [[NSMutableAttributedString alloc] initWithString:lblTermsAndCondition.text];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]}
range:range1];
[attributedText setAttributes:@{NSFontAttributeName:[UIFont fontWithName:fontBold size:12.0]}
range:range2];
[attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:range1];
[attributedText addAttribute:(NSString*)kCTUnderlineStyleAttributeName
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:range2];
lblTermsAndCondition.attributedText = attributedText;
回答by Ankit Goyal
Use the below code. I hope it help for you.
使用下面的代码。我希望它对你有帮助。
NSString *needToChangeStr=@"BOOK";
NSString *display_string=[NSString stringWithFormat:@"This is %@",book];
NSMutableAttributedString *attri_str=[[NSMutableAttributedString alloc]initWithString:display_string];
int begin=[display_string length]-[needToChangeStr length];
int end=[needToChangeStr length];
[attri_str addAttribute:NSFontAttributeName value:[UIFont fontWithName:@"HelveticaNeue-Bold" size:30] range:NSMakeRange(begin, end)];