Как я могу подчеркнуть текст, который может состоять из нескольких строк? Я считаю, что некоторые люди предлагают UIWebView, но это явно слишком тяжелый класс для простого рендеринга текста.
Я думал о том, чтобы выяснить начальную точку и длину каждой строки в каждой строке. И соответственно проведите под ним линию.
У меня возникают проблемы с тем, как определить длину и начальную точку строки.
Я пытался использовать -[UILabel textRectForBounds:limitedToNumberOfLines:]
, это должен быть ограничивающий прямоугольник для текста, верно? Тогда мне нужно работать над выравниванием? Как я могу получить начальную точку каждой линии, если она выровнена по центру и по правому краю?
Ответы:
Вы можете создать подкласс от 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 и вы не хотите использовать сторонние компоненты, приведенный выше код все равно поможет.
источник
В 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);
Или еще лучше вместо переопределения просто используйте OHAttributedLabel, созданный Оливье Халлигоном.
источник
NSMutableAttributedString
Я объединил некоторые из предоставленных ответов, чтобы создать лучший (по крайней мере, для моих требований) подкласс UILabel, который поддерживает:
https://github.com/GuntisTreulands/UnderLineLabel
источник
Людям, которые не хотят создавать подклассы представления (UILabel / UIButton) и т. Д., "ЗабудьтеButton" также можно заменить любой меткой.
-(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)}];
Надеюсь, это поможет ;-)
источник
NSMutableAttributedString *text = [self.myUILabel.attributedText mutableCopy]; [text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)]; self.myUILabel.attributedText = text;
источник
Вы можете создать собственный ярлык с именем UnderlineLabel и отредактировать функцию 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;
источник
Иногда мы, разработчики, застреваем в небольшой части дизайна любого экрана пользовательского интерфейса. Одно из самых раздражающих требований - текст под строкой. Не волнуйтесь, вот решение.
Подчеркивание текста в 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
источник
Расширенная версия кода Ковпаса (цвет и размер линии)
@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]; }
источник
Как показал Ковпас, вы можете использовать ограничивающую рамку в большинстве случаев, хотя не всегда гарантируется, что ограничивающая рамка будет аккуратно вписываться в текст. Поле с высотой 50 и размером шрифта 12 может не дать желаемых результатов в зависимости от конфигурации UILabel.
Запросите UIString в UILabel, чтобы определить его точные метрики, и используйте их, чтобы лучше разместить подчеркивание независимо от ограничивающей рамки или рамки, используя код рисования, уже предоставленный kovpas.
Вам также следует обратить внимание на свойство UIFont "lead", которое определяет расстояние между базовыми линиями на основе определенного шрифта. Базовая линия - это то место, где вы хотите нарисовать подчеркивание.
Посмотрите дополнения 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];
Это было вдохновлено Каримом выше.
источник
Основываясь на ответах Ковпаса и Дэмиена Прака, вот реализация 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]; }
источник
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];
источник
Версия Swift 4.1:
let underlineAttriString = NSAttributedString(string:"attriString", attributes: [NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleSingle.rawValue]) label.attributedText = underlineAttriString
источник
Вы можете использовать этот мой собственный ярлык! Вы также можете использовать построитель интерфейса, чтобы установить
import UIKit class YHYAttributedLabel : UILabel{ @IBInspectable var underlineText : String = ""{ didSet{ self.attributedText = NSAttributedString(string: underlineText, attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue]) } } }
источник