Souligner le texte dans UIlabel

Comment puis-je souligner un texte qui pourrait être constitué de plusieurs lignes de chaîne? Je trouve que certaines personnes suggèrent UIWebView, mais c’est évidemment une classe trop lourde pour le rendu de texte.

Mes pensées étaient de trouver le sharepoint départ et la longueur de chaque chaîne dans chaque ligne. Et tracez une ligne en dessous.

Je rencontre des problèmes pour déterminer la longueur et le sharepoint départ de la chaîne. Quelqu’un peut-il m’aider à ce sujet?

J’ai essayé d’utiliser -[UILabel textRectForBounds:limitedToNumberOfLines:] , ce devrait être le dessin délimitant rect pour le texte à droite? Ensuite, je dois travailler sur l’alignement? Comment puis-je obtenir le sharepoint départ de chaque ligne lorsqu’il est justifié au centre et justifié à droite?

Je suis nouveau ici, alors merci d’avance.

Vous pouvez sous-classer UILabel et remplacer la méthode 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:
À partir d’iOS 6, Apple a ajouté le support NSAtsortingbutedSsortingng à UILabel, alors maintenant c’est beaucoup plus facile et fonctionne pour plusieurs lignes:

 NSDictionary *underlineAtsortingbute = @{NSUnderlineStyleAtsortingbuteName: @(NSUnderlineStyleSingle)}; myLabel.atsortingbutedText = [[NSAtsortingbutedSsortingng alloc] initWithSsortingng:@"Test ssortingng" atsortingbutes:underlineAtsortingbute]; 

Si vous souhaitez toujours prendre en charge iOS 4 et iOS 5, je vous recommande d’utiliser TTTAtsortingbutedLabel plutôt que de souligner manuellement l’étiquette. Cependant, si vous avez besoin de souligner UILabel sur une ligne et que vous ne voulez pas utiliser de composants tiers, le code ci-dessus fera quand même l’affaire.

C’est ce que j’ai fait. Cela fonctionne comme du beurre.

1) Ajoutez CoreText.framework à vos Frameworks.

2) import dans la classe où vous avez besoin d’une étiquette soulignée.

3) Écrivez le code suivant.

  NSMutableAtsortingbutedSsortingng *attSsortingng = [[NSMutableAtsortingbutedSsortingng alloc] initWithSsortingng:@"My Messages"]; [attSsortingng addAtsortingbute:(NSSsortingng*)kCTUnderlineStyleAtsortingbuteName value:[NSNumber numberWithInt:kCTUnderlineStyleSingle] range:(NSRange){0,[attSsortingng length]}]; self.myMsgLBL.atsortingbutedText = attSsortingng; self.myMsgLBL.textColor = [UIColor whiteColor]; 

En Swift:

  let underlineAtsortingSsortingng = NSAtsortingbutedSsortingng(ssortingng:"atsortingSsortingng", atsortingbutes: [NSUnderlineStyleAtsortingbuteName: NSUnderlineStyle.StyleSingle.rawValue]) label.atsortingbutedText = underlineAtsortingSsortingng 

Utilisez une chaîne d’atsortingbut:

 NSMutableAtsortingbutedSsortingng* attrSsortingng = [[NSMutableAtsortingbutedSsortingng alloc] initWithSsortingng:@"Your Ssortingng"] [attrSsortingng addAtsortingbute:(NSSsortingng*)kCTUnderlineStyleAtsortingbuteName value:[NSNumber numberWithInt:kCTUnderlineStyleSingle] range:(NSRange){0,[attrSsortingng length]}]; 

Et ensuite remplacer l’étiquette – (void) drawTextInRect: (CGRect) aRect et rendre le texte dans quelque chose comme:

 CGContextRef ctx = UIGraphicsGetCurrentContext(); CGContextSaveGState(ctx); CTFramesetterRef framesetter = CTFramesetterCreateWithAtsortingbutedSsortingng((CFAtsortingbutedSsortingngRef)attrSsortingng); 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); 

Ou mieux encore, au lieu de passer outre, utilisez le label OHAtsortingbuted créé par Olivier Halligon

J’ai combiné certaines des réponses fournies pour créer une sous-classe UILabel (du moins pour mes besoins) qui supporte:

  • texte multiligne avec différentes limites d’étiquette (le texte peut être au milieu du cadre de l’étiquette ou de la taille exacte)
  • souligner
  • barré
  • Décalage de ligne souligné / barré
  • Alignement du texte
  • différentes tailles de police

https://github.com/GuntisTreulands/UnderLineLabel

Les personnes qui ne veulent pas sous-classer la vue (UILabel / UIButton), etc … ‘forgetButton’ peuvent également être remplacées par n’importe quel repère.

 -(void) drawUnderlinedLabel { NSSsortingng *ssortingng = [forgetButton titleForState:UIControlStateNormal]; CGSize ssortingngSize = [ssortingng sizeWithFont:forgetButton.titleLabel.font]; CGRect buttonFrame = forgetButton.frame; CGRect labelFrame = CGRectMake(buttonFrame.origin.x + buttonFrame.size.width - ssortingngSize.width, buttonFrame.origin.y + ssortingngSize.height + 1 , ssortingngSize.width, 2); UILabel *lineLabel = [[UILabel alloc] initWithFrame:labelFrame]; lineLabel.backgroundColor = [UIColor blackColor]; //[forgetButton addSubview:lineLabel]; [self.view addSubview:lineLabel]; } 
 NSSsortingng *tem =self.detailCustomerCRMCaseLabel.text; if (tem != nil && ![tem isEqualToSsortingng:@""]) { NSMutableAtsortingbutedSsortingng *temSsortingng=[[NSMutableAtsortingbutedSsortingng alloc]initWithSsortingng:tem]; [temSsortingng addAtsortingbute:NSUnderlineStyleAtsortingbuteName value:[NSNumber numberWithInt:1] range:(NSRange){0,[temSsortingng length]}]; self.detailCustomerCRMCaseLabel.atsortingbutedText = temSsortingng; } 

Une autre solution pourrait être (depuis iOS 7) une valeur négative à NSBaselineOffsetAtsortingbuteName , par exemple votre NSAtsortingbutedSsortingng pourrait être:

 NSAtsortingbutedSsortingng *atsortingbutedText = [[NSAtsortingbutedSsortingng alloc] initWithSsortingng:@"my text goes here' atsortingbutes:@{NSFontAtsortingbuteName: [UIFont fontWithName:@"Helvetica-Regular" size:12], NSForegroundColorAtsortingbuteName: [UIColor blackColor], NSUnderlineStyleAtsortingbuteName: @(NSUnderlineStyleSingle), NSBaselineOffsetAtsortingbuteName: @(-3)}]; 

J’espère que cela aidera 😉

 NSMutableAtsortingbutedSsortingng *text = [self.myUILabel.atsortingbutedText mutableCopy]; [text addAtsortingbute:NSUnderlineStyleAtsortingbuteName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)]; self.myUILabel.atsortingbutedText = text; 

Vous pouvez créer une étiquette personnalisée avec le nom UnderlinedLabel et éditer la fonction drawRect.

 #import "UnderlinedLabel.h" @implementation UnderlinedLabel - (void)drawRect:(CGRect)rect { NSSsortingng *normalTex = self.text; NSDictionary *underlineAtsortingbute = @{NSUnderlineStyleAtsortingbuteName: @(NSUnderlineStyleSingle)}; self.atsortingbutedText = [[NSAtsortingbutedSsortingng alloc] initWithSsortingng:normalTex atsortingbutes:underlineAtsortingbute]; [super drawRect:rect]; } 

Voici la solution la plus simple qui fonctionne pour moi sans écrire de codes supplémentaires.

 // To underline text in UILable NSMutableAtsortingbutedSsortingng *text = [[NSMutableAtsortingbutedSsortingng alloc] initWithSsortingng:@"Type your text here"]; [text addAtsortingbute:NSUnderlineStyleAtsortingbuteName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)]; lblText.atsortingbutedText = text; 

Une version améliorée du code de Kovpas (couleur et taille de ligne)

 @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 

J’ai créé pour uilabel multiligne avec soulignement:

Pour la taille de police 8 à 13, définissez int lineHeight = self.font.pointSize + 3;

Pour la taille de police 14 à 20, définissez 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]; } 

Comme kovpas l’a montré, vous pouvez utiliser le cadre de sélection dans la plupart des cas, bien qu’il ne soit pas toujours garanti que le cadre de sélection corresponde parfaitement au texte. Une case avec une hauteur de 50 et une taille de police de 12 peut ne pas donner les résultats souhaités en fonction de la configuration de UILabel.

Interrogez UISsortingng dans UILabel pour déterminer ses mésortingques exactes et utilisez-les pour mieux positionner votre soulignement quel que soit le cadre ou le cadre englobant à l’aide du code de dessin déjà fourni par kovpas.

Vous devez également examiner la propriété “leader” de UIFont qui indique la distance entre les lignes de base en fonction d’une police particulière. La ligne de base est l’endroit où vous souhaitez que votre soulignement soit dessiné.

Recherchez les ajouts UIKit à NSSsortingng:

 (CGSize)sizeWithFont:(UIFont *)font //Returns the size of the ssortingng 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 ssortingng 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 ssortingng if it were rendered with the specified constraints. 

J’utilise une vue en ligne open source et je l’ai simplement ajoutée aux sous-vues de bouton:

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

Ceci a été inspiré par Karim ci-dessus.

Basé sur les réponses de Kovpas & Damien Praca, voici une implémentation de UILabelUnderligned qui supporte également textAlignemnt .

 #import  @interface UILabelUnderlined : UILabel @end 

et la mise en œuvre:

 #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 

Voici une autre solution plus simple (la largeur du soulignement n’est pas la plus précise mais elle était suffisante pour moi)

J’ai un UIView (_view_underline) qui a un arrière-plan blanc, une hauteur de 1 pixel et je mets à jour sa largeur chaque fois que je mets à jour le texte

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

NSUnderlineStyleAtsortingbuteName qui prend un NSNumber (où 0 n’est aucun soulignement) peut être ajouté à un dictionnaire d’atsortingbuts. Je ne sais pas si c’est plus facile. Mais c’était plus facile pour moi.

  NSDictionary *atsortingbutes; atsortingbutes = @{NSFontAtsortingbuteName:font, NSParagraphStyleAtsortingbuteName: style, NSUnderlineStyleAtsortingbuteName:[NSNumber numberWithInteger:1]}; [text drawInRect:CGRectMake(self.contentRect.origin.x, currentY, maximumSize.width, textRect.size.height) withAtsortingbutes:atsortingbutes];