Comment souligner un texte qui pourrait comporter plusieurs lignes de chaîne? .__ Je trouve que certaines personnes suggèrent UIWebView, mais il s'agit évidemment d'une classe trop lourde pour un rendu de texte uniquement.
Mon idée était de déterminer le point de départ et la longueur de chaque chaîne de chaque ligne ..__ Et de dessiner une ligne en conséquence.
Je rencontre des problèmes pour déterminer la longueur et le point de départ de la chaîne. Quelqu'un peut-il m'aider à ce sujet?
J'ai essayé d'utiliser -[UILabel textRectForBounds:limitedToNumberOfLines:]
, cela devrait être le rectangle de délimitation du dessin pour le texte non? Ensuite, je dois travailler sur l’alignement? Comment puis-je obtenir le point de départ de chaque ligne quand elle est justifiée au centre et justifiée à droite?
Je suis nouveau ici, alors merci d'avance.
Vous pouvez sous-classer à partir de UILabel et substituer 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 de iOS 6, Apple a ajouté la prise en charge de Uilabel par NSAttributedString, elle est donc beaucoup plus simple et fonctionne pour plusieurs lignes
NSDictionary *underlineAttribute = @{NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle)};
myLabel.attributedText = [[NSAttributedString alloc] initWithString:@"Test string"
attributes:underlineAttribute];
Si vous souhaitez toujours prendre en charge iOS 4 et iOS 5, nous vous recommandons d'utiliser TTTAttributedLabel plutôt que de souligner manuellement le libellé. Toutefois, si vous avez besoin de souligner UILabel sur une ligne et de ne pas utiliser de composants tiers, le code ci-dessus fera toujours l'affaire.
C'est ce que j'ai fait. Cela fonctionne comme du beurre.
1) Ajoutez CoreText.framework à vos cadres.
2) importez <CoreText/CoreText.h> dans la classe où vous avez besoin d’un libellé souligné.
3) Écris le code suivant.
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];
En rapide:
let underlineAttriString = NSAttributedString(string: "attriString",
attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
label.attributedText = underlineAttriString
Utilisez une chaîne d'attribut:
NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:@"Your String"]
[attrString addAttribute:(NSString*)kCTUnderlineStyleAttributeName
value:[NSNumber numberWithInt:kCTUnderlineStyleSingle]
range:(NSRange){0,[attrString length]}];
Et puis écrasez le libellé - (void) drawTextInRect: (CGRect) aRect et restituez le texte de la manière suivante:
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);
Ou mieux encore, au lieu de remplacer, utilisez simplement le OHAttributedLabel créé par Olivier Halligon
J'ai combiné certaines des réponses fournies pour créer une meilleure sous-classe UILabel (du moins pour mes besoins), qui prend en charge:
Les personnes qui ne souhaitent pas sous-classer la vue (UILabel/UIButton), etc., etc., peuvent également être remplacées par une étiquette.
-(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;
}
NSMutableAttributedString *text = [self.myUILabel.attributedText mutableCopy];
[text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)];
self.myUILabel.attributedText = text;
Une autre solution pourrait être (depuis iOS 7) de donner une valeur négative à NSBaselineOffsetAttributeName
, par exemple votre NSAttributedString
pourrait être:
NSAttributedString *attributedText = [[NSAttributedString alloc] initWithString:@"my text goes here'
attributes:@{NSFontAttributeName: [UIFont fontWithName:@"Helvetica-Regular" size:12],
NSForegroundColorAttributeName: [UIColor blackColor],
NSUnderlineStyleAttributeName: @(NSUnderlineStyleSingle), NSBaselineOffsetAttributeName: @(-3)}];
J'espère que ça va aider ;-)
Voici la solution la plus simple qui fonctionne pour moi sans écrire de codes supplémentaires.
// 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;
Vous pouvez créer une étiquette personnalisée avec le nom UnderlinedLabel et modifier la fonction 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];
}
Une version améliorée du code de Kovpas (couleur et taille de trait)
@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 une taille de police de 8 à 13, définissez int lineHeight = self.font.pointSize + 3;
Pour une taille de police de 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];
}
NSUnderlineStyleAttributeName qui prend un NSNumber (où 0 n'est pas souligné) peut être ajouté à un dictionnaire d'attributs .. Je ne sais pas si c'est plus facile Mais c'était plus facile pour mes objectifs.
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];
Voici une autre solution plus simple (la largeur du soulignement n’est pas très précise mais c’est suffisant pour moi)
J'ai un (_view_underline)
UIView qui a un fond blanc, une hauteur de 1 pixel et je modifie 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];
}
Basé sur les réponses de Kovpas & Damien Praca, voici une implémentation de UILabelUnderligned qui prend également en charge textAlignemnt .
#import <UIKit/UIKit.h>
@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
Swift 4.1 ver:
let underlineAttriString = NSAttributedString(string:"attriString", attributes:
[NSAttributedStringKey.underlineStyle: NSUnderlineStyle.styleSingle.rawValue])
label.attributedText = underlineAttriString
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 s'intègrera parfaitement au texte. Une boîte d'une hauteur de 50 et d'une taille de police de 12 peut ne pas donner les résultats souhaités selon la configuration UILabel.
Interrogez UIString dans UILabel pour déterminer ses métriques exactes et utilisez-les pour mieux placer votre soulignement, quel que soit le cadre de sélection ou le cadre englobant, à l'aide du code de dessin déjà fourni par kovpas.
Vous devriez également regarder la propriété "principale" d'UIFont qui donne 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 tracé.
Recherchez les ajouts d'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.
J'utilise une vue en ligne open source que je viens d'ajouter aux sous-vues des boutons:
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.