Подчеркните текст в UIlabel - PullRequest
       138

Подчеркните текст в UIlabel

81 голосов
/ 26 апреля 2010

Как я могу подчеркнуть текст, который может состоять из нескольких строк? Я считаю, что некоторые люди предлагают UIWebView, но это явно слишком тяжелый класс для простого рендеринга текста.

Я думал о том, чтобы выяснить начальную точку и длину каждой строки в каждой строке. И нарисуйте линию под ним соответственно.

У меня возникают проблемы с определением длины и начальной точки строки.

Я пытался использовать -[UILabel textRectForBounds:limitedToNumberOfLines:], это должен быть ограничивающий прямоугольник для текста, верно? Тогда я должен работать над выравниванием? Как я могу получить начальную точку каждой линии, если она выровнена по центру и выровнена по правому краю?

Ответы [ 19 ]

3 голосов
/ 11 января 2016

Вы можете создать собственную метку с именем 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];
}
1 голос
/ 19 мая 2011

Усовершенствованная версия кода 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
1 голос
/ 25 августа 2011

Я создал для многострочного 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]; 
}
0 голосов
/ 26 апреля 2010

Как показал kovpas, вы можете использовать ограничивающий прямоугольник в большинстве случаев, хотя не всегда гарантируется, что ограничивающий прямоугольник будет аккуратно помещаться вокруг текста. Поле с высотой 50 и размером шрифта 12 может не дать желаемых результатов в зависимости от конфигурации UILabel.

Запрос UIString в UILabel, чтобы определить его точные метрики и использовать их для лучшего размещения подчеркивания независимо от ограничивающей рамки или рамки, используя код чертежа, уже предоставленный 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 голосов
/ 19 июля 2017

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];
0 голосов
/ 19 июля 2012

На основе ответов 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
0 голосов
/ 07 октября 2011

Я использую вид строки с открытым исходным кодом и просто добавил его в подпредставления кнопки:

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

Это было вдохновлено Каримом выше.

0 голосов
/ 12 сентября 2018

Swift 4.1 ver:

 let underlineAttriString = NSAttributedString(string:"attriString", attributes:
    [NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleSingle.rawValue])

label.attributedText = underlineAttriString
0 голосов
/ 14 ноября 2012

Вот еще одно, более простое решение (ширина подчеркивания не самая точная, но для меня это было достаточно хорошо)

У меня есть 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];
}
...