2010-04-26 99 views
77

如何爲文本加下劃線,可以是多行字符串? 我發現有人提出了UIWebView,但它顯然太重了一個類的文本渲染。UIlabel中的下劃線文本

我的想法是找出每一行中每個字符串的起點和長度。 並在其下面畫一條線。

我遇到了如何計算字符串的長度和起點的問題。有人可以幫助我嗎?

我試過用-[UILabel textRectForBounds:limitedToNumberOfLines:],這個應該是對文本的繪製邊界矩形吧? 然後我必須在對齊上工作? 如何獲得每行的中心對齊和右對齊的起點?

我是新來的,所以先謝謝你。

+1

看看[我這篇文章(http://davidjhinson.wordpress.com/2009/11/26/underline-text-on-the-iphone/) – Casebash 2010-10-07 03:39:26

回答

132

你可以從的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中蘋果增加NSAttributedString對的UILabel支持,所以現在它更容易和作品多行:

NSDictionary *underlineAttribute = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)}; 
myLabel.attributedText = [[NSAttributedString alloc] initWithString:@"Test string" 
                 attributes:underlineAttribute]; 

如果你仍然希望支持iOS 4和iOS 5,我會建議結束使用TTTAttributedLabel而不是手動標註下劃線標籤。但是,如果您需要強調單行UILabel並且不想使用第三方組件,上面的代碼仍然可以解決問題。

+3

我想這隻會得出一個爲下劃線字符串的最後一行,對嗎?對於其他行中的字符串下劃線怎麼樣? – semix 2010-04-26 07:29:16

+2

它不會做多行,但這是我能找到的最好的,所以我想多行是不可能的。我猜想我能想到的下一個最佳解決方案是導入一個字體內置下劃線的字體。這隻適用於可以導入字體的ios 4.0+。 – DonnaLea 2011-09-08 05:45:51

+0

嗨,我想知道這是否違反任何ios ui標準。 – thndrkiss 2011-10-02 07:25:33

0

正如kovpas所示,在大多數情況下您可以使用邊界框,但並不總能保證邊界框將整齊地放在文本週圍。根據UILabel配置,高度爲50,字體大小爲12的框可能不會提供所需的結果。

查詢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. 
+0

肯尼 看來我可以使用3種方法輕鬆獲得第一行文本的寬度,但第二條第三行和其他行怎麼樣? 你能舉個例子嗎? – semix 2010-04-26 08:19:49

+0

我必須承認。現在有辦法使用NSString來實現你想要的,除非別人有更多的東西要提供。我將不得不建議其他人一樣在我面前使用的UIWebView和東西你的文本到視圖: [webView的loadHTMLString:@基本URL「下劃線文字」:無]。 讓它做線的佈局和確定。 如果你想要第n行加下劃線並且你不知道哪一行是第n行,那是另一回事。 – gnasher 2010-04-27 12:14:11

11

的人,不想子類的觀點(的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]; 
} 
+1

-1用於調用「draw ...」分配UILabel並將其添加到視圖的方法。 – jcayzac 2012-11-14 05:45:43

+1

我已將其調整爲更具通用性:http://pastebin.com/QkF9ifpb原始不包含標籤在子視圖中。 – Fonix 2013-02-08 12:58:32

1

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 
+0

不做多行。 – 2012-08-25 03:22:36

1

我已經創建用於多線的UILabel與下劃線的增強版本:

對於字體大小8到13集INT lineHeight是= self.font。的pointsize + 3;

對於字體大小14至20 set 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]; 
} 
0

我使用開放源極線圖,只是它添加到按鈕子視圖:

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上面的啓發。

+0

你可以使用UIVIew。 UIView * line = [[UIView alloc] initWithFrame:frame]; line.backgroundColor = [UIColor lightGrayColor]; – dzeikei 2012-03-01 01:44:01

19

使用屬性字符串:

NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:@"Your String"] 
[attrString addAttribute:(NSString*)kCTUnderlineStyleAttributeName 
        value:[NSNumber numberWithInt:kCTUnderlineStyleSingle] 
        range:(NSRange){0,[attrString length]}]; 

,然後覆蓋的標籤 - (空)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

+1

最上面一行應該是'NSMutableAttributedString' – borrrden 2012-05-16 02:40:48

+0

我使用OHAttributedLabel放棄的原因是 - 至少對我來說,無法計算準確的文本高度。在10%的情況下,這是不正確的。 (也許因爲我用不同的字體..) – 2012-09-28 13:11:42

0

基於Kovpas &達米安普拉卡的答案,這裏是一個實現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 
+0

更新爲iOS 6開關: 開關(self.textAlignment){ 情況NSTextAlignmentLeft: 情況NSTextAlignmentJustified: 情況NSTextAlignmentNatural: 中斷; case NSTextAlignmentCenter: alignementXOffset =(self.titleLabel.frame.size.width - textSize.width)/ 2; 休息; case NSTextAlignmentRight: alignementXOffset = self.titleLabel.frame.size.width - textSize.width; 休息; } – pfrank 2013-10-13 17:06:26

16

我結合一些提供答案,創造更好的(至少對我的要求)的UILabel子類,它支持:

  • 多帶有各種標籤邊界的文本(文本可以位於標籤框架的中間或準確尺寸)
  • 下劃線
  • 三振
  • 下劃線/刪除線線偏移
  • 文本對齊
  • 不同的字體大小

https://github.com/GuntisTreulands/UnderLineLabel

+0

該代碼已過時,不起作用。 – turingtested 2015-06-25 18:48:04

+0

仍然適用於我的結局。 – 2015-06-25 20:06:54

0

下面是另一個,簡單的解決方案(下劃線的寬度不是最準確的,但它是不夠好對我來說)

我有一個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]; 
} 
8
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; 
} 
+0

僅供參考,這隻適用於iOS 6.0+ – odyth 2013-03-12 23:28:05

37

這就是我所做的。它的作用像黃油。

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]; 
+0

+1這個答案,因爲這確實很出色,它也演示了一種簡單的方法來設置特定的字符範圍(這是我自己需要的)。謝謝! - Erik – 2015-01-22 23:34:44

29

在夫特:

let underlineAttriString = NSAttributedString(string:"attriString", attributes: 
     [NSUnderlineStyleAttributeName: NSUnderlineStyle.StyleSingle.rawValue]) 

    label.attributedText = underlineAttriString 
+0

Swift 3中唯一需要做的事情就是將.StyleSingle改爲.styleSingle,它在Swift3中是camelCased的,但是很好的答案! – 2017-03-21 22:39:32

+0

沒有.rawValue,這導致我崩潰。 – jackofallcode 2017-10-31 15:11:35

7

另一種解決方案可以被(因爲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)}]; 

希望這將幫助;-)

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]; 
} 
6
NSMutableAttributedString *text = [self.myUILabel.attributedText mutableCopy]; 
[text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)]; 
self.myUILabel.attributedText = text; 
3

這裏是一個無需編寫附加代碼對我的作品最簡單的解決方案。

// 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; 
0

NSUnderlineStyleAttributeName這需要一個NSNumber(其中0是無下劃線)可以被添加到一個屬性詞典。 我不知道這是否更容易。但是,這對我的目的更容易。

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];