如何在可能是多行字符串的文本下划线?我发现有人建议使用UIWebView,但是对于仅用于文本呈现的类来说,它显然太重了。
我的想法是弄清楚每行中每个字符串的起点和长度。并在其下画一条线。
我在如何计算字符串的长度和起始点时遇到问题。
我尝试使用-[UILabel textRectForBounds:limitedToNumberOfLines:]
,这应该是文本的图形边界矩形吗?那我必须进行对齐吗?当中心对齐并右对齐时,如何获得每条线的起点?
Answers:
您可以从UILabel继承子类,并重写drawRect方法:
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSetRGBStrokeColor(ctx, 207.0f/255.0f, 91.0f/255.0f, 44.0f/255.0f, 1.0f); // RGBA
CGContextSetLineWidth(ctx, 1.0f);
CGContextMoveToPoint(ctx, 0, self.bounds.size.height - 1);
CGContextAddLineToPoint(ctx, self.bounds.size.width, self.bounds.size.height - 1);
CGContextStrokePath(ctx);
[super drawRect:rect];
}
UPD:
从iOS 6开始,Apple为UILabel添加了NSAttributedString支持,因此现在它变得更加简单并且可以用于多行:
NSDictionary *underlineAttribute = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
myLabel.attributedText = [[NSAttributedString alloc] initWithString:@"Test string"
attributes:underlineAttribute];
如果您仍然希望支持iOS 4和iOS 5,建议您使用TTTAttributedLabel,而不要手动添加下划线标签。但是,如果您需要在单行UILabel下划线,并且不想使用第三方组件,则上面的代码仍然可以解决问题。
在Swift中:
let underlineAttriString = NSAttributedString(string: "attriString",
attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
label.attributedText = underlineAttriString
这就是我所做的。它像黄油一样工作。
1)将CoreText.framework添加到您的框架中。
2)在需要下划线标签的类中导入<CoreText / CoreText.h>。
3)编写以下代码。
NSMutableAttributedString *attString = [[NSMutableAttributedString alloc] initWithString:@"My Messages"];
[attString addAttribute:(NSString*)kCTUnderlineStyleAttributeName
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:(NSRange){0,[attString length]}];
self.myMsgLBL.attributedText = attString;
self.myMsgLBL.textColor = [UIColor whiteColor];
使用属性字符串:
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:@"Your String"]
[attrString addAttribute:(NSString*)kCTUnderlineStyleAttributeName
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:(NSRange){0,[attrString length]}];
然后覆盖标签-(void)drawTextInRect:(CGRect)aRect并以类似以下方式呈现文本:
CGContextRef ctx = UIGraphicsGetCurrentContext();
CGContextSaveGState(ctx);
CTFramesetterRef framesetter = CTFramesetterCreateWithAttributedString((CFAttributedStringRef)attrString);
drawingRect = self.bounds;
CGMutablePathRef path = CGPathCreateMutable();
CGPathAddRect(path, NULL, drawingRect);
textFrame = CTFramesetterCreateFrame(framesetter,CFRangeMake(0,0), path, NULL);
CGPathRelease(path);
CFRelease(framesetter);
CTFrameDraw(textFrame, ctx);
CGContextRestoreGState(ctx);
或更好的方法是使用Olivier Halligon创建的OHAttributedLabel而不是覆盖
NSMutableAttributedString
我结合了提供的一些答案,以创建更好的(至少是出于我的要求)UILabel子类,该子类支持:
不想将视图子类化(UILabel / UIButton)等的人...'forgetButton'也可以用任何标签代替。
-(void) drawUnderlinedLabel {
NSString *string = [forgetButton titleForState:UIControlStateNormal];
CGSize stringSize = [string sizeWithFont:forgetButton.titleLabel.font];
CGRect buttonFrame = forgetButton.frame;
CGRect labelFrame = CGRectMake(buttonFrame.origin.x + buttonFrame.size.width - stringSize.width,
buttonFrame.origin.y + stringSize.height + 1 ,
stringSize.width, 2);
UILabel *lineLabel = [[UILabel alloc] initWithFrame:labelFrame];
lineLabel.backgroundColor = [UIColor blackColor];
//[forgetButton addSubview:lineLabel];
[self.view addSubview:lineLabel];
}
NSString *tem =self.detailCustomerCRMCaseLabel.text;
if (tem != nil && ![tem isEqualToString:@""]) {
NSMutableAttributedString *temString=[[NSMutableAttributedString alloc]initWithString:tem];
[temString addAttribute:NSUnderlineStyleAttributeName
value:[NSNumber numberWithInt:1]
range:(NSRange){0,[temString length]}];
self.detailCustomerCRMCaseLabel.attributedText = temString;
}
另一个解决方案可能是(自iOS 7起)为赋予负值NSBaselineOffsetAttributeName
,例如,您NSAttributedString
可以是:
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:@"my text goes here'
attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Helvetica-Regular" size:12],
NSForegroundColorAttributeName: [UIColor blackColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSBaselineOffsetAttributeName: @(-3)}];
希望这会有所帮助;-)
您可以创建名称为UnderlinedLabel的自定义标签并编辑drawRect函数。
#import "UnderlinedLabel.h"
@implementation UnderlinedLabel
- (void)drawRect:(CGRect)rect
{
NSString *normalTex = self.text;
NSDictionary *underlineAttribute = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
self.attributedText = [[NSAttributedString alloc] initWithString:normalTex
attributes:underlineAttribute];
[super drawRect:rect];
}
这是最简单的解决方案,无需编写其他代码即可对我有效。
// To underline text in UILable
NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:@"Type your text here"];
[text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)];
lblText.attributedText = text;
有时,我们开发人员陷入了任何UI屏幕的小型设计部分中。最令人讨厌的要求之一是在行文本下。不用担心,这是解决方案。
使用Objective C在UILabel中给文本加下划线
UILabel *label=[[UILabel alloc]initWithFrame:CGRectMake(0, 0, 320, 480)];
label.backgroundColor=[UIColor lightGrayColor];
NSMutableAttributedString *attributedString;
attributedString = [[NSMutableAttributedString alloc] initWithString:@"Apply Underlining"];
[attributedString addAttribute:NSUnderlineStyleAttributeName value:@1 range:NSMakeRange(0,
[attributedString length])];
[label setAttributedText:attributedString];
使用Swift在UILabel中给文本加下划线
label.backgroundColor = .lightGray
let attributedString = NSMutableAttributedString.init(string: "Apply UnderLining")
attributedString.addAttribute(NSUnderlineStyleAttributeName, value: 1, range:
NSRange.init(location: 0, length: attributedString.length))
label.attributedText = attributedString
Kovpas代码的增强版本(颜色和行大小)
@implementation UILabelUnderlined
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
const CGFloat* colors = CGColorGetComponents(self.textColor.CGColor);
CGContextSetRGBStrokeColor(ctx, colors[0], colors[1], colors[2], 1.0); // RGBA
CGContextSetLineWidth(ctx, 1.0f);
CGSize tmpSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(200, 9999)];
CGContextMoveToPoint(ctx, 0, self.bounds.size.height - 1);
CGContextAddLineToPoint(ctx, tmpSize.width, self.bounds.size.height - 1);
CGContextStrokePath(ctx);
[super drawRect:rect];
}
@end
我已经为带有下划线的多行uilabel创建了:
对于8至13的字体,设置int lineHeight = self.font.pointSize + 3;
对于14到20的字体,设置int lineHeight = self.font.pointSize + 4;
- (void)drawRect:(CGRect)rect
{
CGContextRef ctx = UIGraphicsGetCurrentContext();
const CGFloat* colors = CGColorGetComponents(self.textColor.CGColor);
CGContextSetRGBStrokeColor(ctx, colors[0], colors[1], colors[2], 1.0); // RGBA
CGContextSetLineWidth(ctx, 1.0f);
CGSize tmpSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(self.frame.size.width, 9999)];
int height = tmpSize.height;
int lineHeight = self.font.pointSize+4;
int maxCount = height/lineHeight;
float totalWidth = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(1000, 9999)].width;
for(int i=1;i<=maxCount;i++)
{
float width=0.0;
if((i*self.frame.size.width-totalWidth)<=0)
width = self.frame.size.width;
else
width = self.frame.size.width - (i* self.frame.size.width - totalWidth);
CGContextMoveToPoint(ctx, 0, lineHeight*i-1);
CGContextAddLineToPoint(ctx, width, lineHeight*i-1);
}
CGContextStrokePath(ctx);
[super drawRect:rect];
}
如kovpas所示,尽管并非总是保证边界框可以整齐地围绕文本,但在大多数情况下都可以使用边界框。高度为50且字体大小为12的框可能无法提供所需的结果,具体取决于UILabel配置。
在UILabel中查询UIString以确定其确切的度量标准,并使用这些参数更好地放置下划线,而不必使用kovpas已经提供的绘图代码来包围边框或框架。
您还应该查看UIFont的“前导”属性,该属性根据特定字体给出基线之间的距离。基线是您希望绘制下划线的位置。
查找UIKit对NSString的添加:
(CGSize)sizeWithFont:(UIFont *)font
//Returns the size of the string if it were to be rendered with the specified font on a single line.
(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size
// Returns the size of the string if it were rendered and constrained to the specified size.
(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size lineBreakMode:(UILineBreakMode)lineBreakMode
//Returns the size of the string if it were rendered with the specified constraints.
我使用开放源代码行视图,并将其添加到按钮子视图中:
UILabel *label = termsButton.titleLabel;
CGRect frame = label.frame;
frame.origin.y += frame.size.height - 1;
frame.size.height = 1;
SSLineView *line = [[SSLineView alloc] initWithFrame:frame];
line.lineColor = [UIColor lightGrayColor];
[termsButton addSubview:line];
这是受到上面Karim的启发的。
基于Kovpas和Damien Praca的答案,这是UILabelUnderligned的实现,该实现也支持textAlignemnt。
#import <UIKit/UIKit.h>
@interface UILabelUnderlined : UILabel
@end
和实现:
#import "UILabelUnderlined.h"
@implementation DKUILabel
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
- (void)drawRect:(CGRect)rect {
CGContextRef ctx = UIGraphicsGetCurrentContext();
const CGFloat* colors = CGColorGetComponents(self.textColor.CGColor);
CGContextSetRGBStrokeColor(ctx, colors[0], colors[1], colors[2], 1.0); // RGBA
CGContextSetLineWidth(ctx, 1.0f);
CGSize textSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(200, 9999)];
// handle textAlignement
int alignementXOffset = 0;
switch (self.textAlignment) {
case UITextAlignmentLeft:
break;
case UITextAlignmentCenter:
alignementXOffset = (self.frame.size.width - textSize.width)/2;
break;
case UITextAlignmentRight:
alignementXOffset = self.frame.size.width - textSize.width;
break;
}
CGContextMoveToPoint(ctx, alignementXOffset, self.bounds.size.height - 1);
CGContextAddLineToPoint(ctx, alignementXOffset+textSize.width, self.bounds.size.height - 1);
CGContextStrokePath(ctx);
[super drawRect:rect];
}
@end
这是另一个更简单的解决方案(下划线的宽度不是最准确,但是对我来说足够了)
我有一个UIView (_view_underline)
,背景为白色,高度为1像素,每次更新文本时都会更新其宽度
// It's a shame you have to do custom stuff to underline text
- (void) underline {
float width = [[_txt_title text] length] * 10.0f;
CGRect prev_frame = [_view_underline frame];
prev_frame.size.width = width;
[_view_underline setFrame:prev_frame];
}
可以将带有NSNumber(其中0不为下划线)的NSUnderlineStyleAttributeName添加到属性字典中。我不知道这是否更容易。但是,对我而言,这更容易。
NSDictionary *attributes;
attributes = @{NSFontAttributeName:font, NSParagraphStyleAttributeName: style, NSUnderlineStyleAttributeName:[NSNumber numberWithInteger:1]};
[text drawInRect:CGRectMake(self.contentRect.origin.x, currentY, maximumSize.width, textRect.size.height) withAttributes:attributes];
您可以使用我的自定义标签!您也可以使用界面构建器进行设置
import UIKit
class YHYAttributedLabel : UILabel{
@IBInspectable
var underlineText : String = ""{
didSet{
self.attributedText = NSAttributedString(string: underlineText,
attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
}
}
}