Подтвердить что ты не робот

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

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

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

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

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

4b9b3361

Ответ 1

Вы можете подклассом из 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 добавила поддержку NSAttributedString для UILabel, поэтому теперь она намного проще и работает для нескольких строк:

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

Если вы все еще хотите поддерживать iOS 4 и iOS 5, я рекомендую использовать TTTAttributedLabel, а не подчеркивать метку вручную. Однако, если вам нужно подчеркнуть однолинейный UILabel и не хотите использовать сторонние компоненты, код выше все равно будет делать трюк.

Ответ 2

Это то, что я сделал. Он работает как масло.

1) Добавьте CoreText.framework в свои рамки.

2) import < 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];

Ответ 3

В Свифте:

let underlineAttriString = NSAttributedString(string: "attriString",
                                          attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
label.attributedText = underlineAttriString

Ответ 4

Используйте строку атрибута:

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

Или лучше, но вместо того, чтобы переопределять, используйте OHAttributedLabel, созданный Оливье Хэллигоном

Ответ 5

Я объединил некоторые из предоставленных ответов, чтобы создать лучший (по крайней мере для моих требований) подкласс UILabel, который поддерживает:

  • многострочный текст с различными границами меток (текст может находиться в середине рамки метки или точного размера)
  • подчеркивание
  • вычеркнуто
  • смещение линии подчеркивания/аута
  • выравнивание текста
  • различные размеры шрифта

https://github.com/GuntisTreulands/UnderLineLabel

Ответ 6

Люди, которые не хотят подклассифицировать представление (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];
}

Ответ 7

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

Ответ 8

Другим решением может быть (начиная с 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)}];

Надеюсь, это поможет; -)

Ответ 9

NSMutableAttributedString *text = [self.myUILabel.attributedText mutableCopy];
[text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)];
self.myUILabel.attributedText = text;

Ответ 10

Вы можете создать пользовательскую метку с именем 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];
}

Ответ 11

Вот самое простое решение, которое работает для меня без написания дополнительных кодов.

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

Ответ 12

Расширенная версия кода 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

Ответ 13

Я создал для многострочной 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]; 
}

Ответ 14

Как показал 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.

Ответ 15

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

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

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

Ответ 16

Основываясь на ответах 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

Ответ 17

Здесь другое, более простое решение (ширина подчеркивания не самая точная, но для меня это было достаточно)

У меня есть UIView (_view_underline), который имеет белый фон, высоту 1 пиксель, и я обновляю его ширину каждый раз, когда я обновляю текст

// It 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];
}

Ответ 18

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

Ответ 19

Swift 4.1 ver:

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

label.attributedText = underlineAttriString

Ответ 20

Иногда мы, разработчик, застряли в небольшой части дизайна любого экрана пользовательского интерфейса. Одним из самых раздражающих требований является текст под строкой. Не волнуйтесь, вот решение.

enter image description here

Подчеркивание текста в UILabel с использованием Objective C

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

Подчеркивание текста в UILabel с помощью Swift

 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