Unterstreichen Sie den Text in UIlabel

88

Wie kann ich einen Text unterstreichen, der aus mehreren Zeichenfolgen bestehen kann? Ich finde, einige Leute schlagen UIWebView vor, aber es ist offensichtlich eine zu schwere Klasse, um nur Text zu rendern.

Meine Gedanken waren, den Startpunkt und die Länge jeder Saite in jeder Zeile herauszufinden. Und ziehen Sie entsprechend eine Linie darunter.

Ich habe Probleme, die Länge und den Startpunkt der Zeichenfolge herauszufinden.

Ich habe versucht zu verwenden -[UILabel textRectForBounds:limitedToNumberOfLines:], dies sollte die Zeichnungsgrenze für den Text sein, oder? Dann muss ich an der Ausrichtung arbeiten? Wie kann ich den Startpunkt jeder Linie ermitteln, wenn sie mittig und rechtsbündig ist?

Semix
quelle
1
Schauen Sie sich diesen Blogpost an
Casebash

Antworten:

137

Sie können eine Unterklasse von UILabel erstellen und die drawRect-Methode überschreiben:

- (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:
Ab iOS 6 hat Apple die NSAttributedString-Unterstützung für UILabel hinzugefügt. Jetzt ist es viel einfacher und funktioniert für mehrere Zeilen:

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

Wenn Sie weiterhin iOS 4 und iOS 5 unterstützen möchten, würde ich empfehlen, TTTAttributedLabel zu verwenden, anstatt das Label manuell zu unterstreichen. Wenn Sie jedoch einzeiliges UILabel unterstreichen müssen und keine Komponenten von Drittanbietern verwenden möchten, reicht der obige Code immer noch aus.

Kovpas
quelle
3
Ich denke, dies wird nur eine Unterstreichung für die letzte Zeile der Zeichenfolge zeichnen, oder? Was ist mit der Unterstreichung für die Zeichenfolge in anderen Zeilen?
Semix
2
Es werden nicht mehrere Zeilen verwendet, aber dies ist das Beste, was ich finden kann. Ich denke, mehrere Zeilen kommen nicht in Frage. Ich denke, die nächstbeste Lösung, die ich mir vorstellen kann, besteht darin, eine Schriftart zu importieren, in die eine Unterstreichung integriert ist. Dies funktioniert nur ab iOS 4.0, wo Sie Schriftarten importieren können.
DonnaLea
Hallo, ich möchte wissen, ob dies gegen einen der ios ui-Standards verstößt.
thndrkiss
Apples Implementierung (der zweite Vorschlag) unterstützt keine Zeichen, die unter der Linie liegen? screencast.com/t/NGvQJqoWAD3J
PFrank
Wenn wir die NSAttributedString-Unterstützung für UILabel verwenden, wird bei Alphabeten wie g die Unterstreichung p & q abgeschnitten. Jemand, der mit dem Problem konfrontiert ist? Beispiel: Login
dev4u
46

In Swift:

let underlineAttriString = NSAttributedString(string: "attriString",
                                          attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
label.attributedText = underlineAttriString
ytll21
quelle
Das einzige, was Sie in Swift 3 tun müssen, ist das Ändern von .StyleSingle in .styleSingle. Es ist in Swift3 camelCased, aber eine großartige Antwort!
Josh O'Connor
Ohne .rawValue verursachte dies einen Absturz für mich.
Jackofallcode
Sie würden nur .rawValue für schnelle 4.0
Carrotzoe
38

Das habe ich getan. Es funktioniert wie Butter.

1) Fügen Sie CoreText.framework zu Ihren Frameworks hinzu.

2) Importieren Sie <CoreText / CoreText.h> in die Klasse, in der Sie eine unterstrichene Bezeichnung benötigen.

3) Schreiben Sie den folgenden Code.

    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];
Sana
quelle
+1 von mir für diese Antwort, da dies in der Tat hervorragend funktioniert und eine einfache Möglichkeit darstellt, auch einen bestimmten Zeichenbereich festzulegen (was ich selbst brauchte). Vielen Dank! - Erik
Erik van der Neut
19

Verwenden Sie eine Attributzeichenfolge:

NSMutableAttributedString* attrString = [[NSMutableAttributedString alloc] initWithString:@"Your String"]
[attrString addAttribute:(NSString*)kCTUnderlineStyleAttributeName 
                   value:[NSNumber numberWithInt:kCTUnderlineStyleSingle] 
                   range:(NSRange){0,[attrString length]}];

Und dann überschreiben Sie die Beschriftung - (void) drawTextInRect: (CGRect) aRect und rendern Sie den Text wie folgt:

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

Oder besser noch, anstatt zu überschreiben, verwenden Sie einfach das von Olivier Halligon erstellte OHAttributedLabel

Paulo Ferreira
quelle
1
Die oberste Zeile sollteNSMutableAttributedString
borrrden
Der Grund, warum ich mit OHAttributedLabel abgelegt habe, war, dass es zumindest für mich nicht möglich war, die genaue Texthöhe zu berechnen. in 10% der Fälle war es falsch. (Vielleicht, weil ich eine andere Schriftart verwendet habe.)
Guntis Treulands
15

Ich habe einige der bereitgestellten Antworten kombiniert, um eine bessere (zumindest für meine Anforderungen) UILabel-Unterklasse zu erstellen, die Folgendes unterstützt:

  • Mehrzeiliger Text mit verschiedenen Beschriftungsgrenzen (Text kann sich in der Mitte des Beschriftungsrahmens befinden oder eine genaue Größe haben)
  • unterstreichen
  • Streik
  • Versatz der Unterstreichungs- / Strikeout-Linie
  • Textausrichtung
  • verschiedene Schriftgrößen

https://github.com/GuntisTreulands/UnderLineLabel

Guntis Treulands
quelle
11

Personen, die die Ansicht nicht unterordnen möchten (UILabel / UIButton) usw. ... 'compareButton' kann auch durch ein beliebiges Etikett ersetzt werden.

-(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];
}
Karim
quelle
2
-1 für den Aufruf von "draw ...", einer Methode, die ein UILabel zuweist und es der Ansicht hinzufügt.
JCayzac
1
Ich habe dies etwas allgemeiner angepasst: pastebin.com/QkF9ifpb Original berücksichtigt nicht, ob sich das Etikett in einer Unteransicht befindet.
Fonix
8
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;
}
Jill Wong
quelle
7

Eine andere Lösung könnte (seit iOS 7) einen negativen Wert erhalten NSBaselineOffsetAttributeName, zum Beispiel 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)}];

Hoffe das wird helfen ;-)

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

Sie können eine benutzerdefinierte Beschriftung mit dem Namen UnderlinedLabel erstellen und die Funktion drawRect bearbeiten.

#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];
}
nfinfu
quelle
3

Hier ist die einfachste Lösung, die für mich funktioniert, ohne zusätzliche Codes zu schreiben.

// 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;
Dhaval Dobariya
quelle
3

Manchmal stecken wir Entwickler in einem kleinen Design-Teil eines UI-Bildschirms. Eine der irritierendsten Anforderungen ist der Zeilentext. Keine Sorge, hier ist die Lösung.

Geben Sie hier die Bildbeschreibung ein

Unterstreichen eines Textes in einem UILabel mit Ziel 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];

Unterstreichen eines Textes in UILabel mit 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
Mr.Javed Multani
quelle
1

Eine erweiterte Version des Codes von Kovpas (Farbe und Liniengröße)

@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
Damien Praca
quelle
1

Ich habe für mehrzeiliges Uilabel mit Unterstreichung erstellt:

Für die Schriftgröße 8 bis 13 setzen Sie int lineHeight = self.font.pointSize + 3;

Für die Schriftgrößen 14 bis 20 setzen Sie 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]; 
}
Piyush
quelle
0

Wie kovpas gezeigt hat, können Sie den Begrenzungsrahmen in den meisten Fällen verwenden, obwohl nicht immer garantiert ist, dass der Begrenzungsrahmen genau um den Text passt. Eine Box mit einer Höhe von 50 und einer Schriftgröße von 12 liefert je nach UILabel-Konfiguration möglicherweise nicht die gewünschten Ergebnisse.

Fragen Sie den UIString innerhalb des UILabels ab, um die genauen Metriken zu ermitteln, und verwenden Sie diese, um Ihre Unterstreichung unabhängig vom umschließenden Begrenzungsrahmen oder Rahmen mithilfe des bereits von kovpas bereitgestellten Zeichnungscodes besser zu platzieren.

Sie sollten sich auch die "führende" Eigenschaft von UIFont ansehen, die den Abstand zwischen Baselines basierend auf einer bestimmten Schriftart angibt. In der Grundlinie soll Ihre Unterstreichung gezeichnet werden.

Suchen Sie nach den UIKit-Ergänzungen zu 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.
Gnasher
quelle
Kenny, es scheint, ich kann die 3 Methoden verwenden, um die Breite der 1. Textzeile leicht zu ermitteln, aber wie steht es mit der 2. 3. und anderen Zeilen? Kannst du ein Beispiel geben?
Semix
Ich muss zugeben. Es gibt jetzt eine Möglichkeit, mit NSString das zu erreichen, was Sie möchten, es sei denn, jemand anderes hat mehr zu bieten. Ich muss wie die anderen vor mir vorschlagen, UIWebView zu verwenden und Ihren Text in die Ansicht einzufügen: [webView loadHTMLString: @ "<html> <u> Unterstrichener Text. </ U> </ html>" baseURL: nil ]; Lassen Sie es das Layout und die Bestimmung, wohin die Linien gehen sollen. Wenn Sie die n-te Zeile unterstrichen haben möchten und nicht wissen können, welche die n-te Zeile ist, ist dies eine andere Angelegenheit.
Gnasher
0

Ich verwende eine Open-Source-Zeilenansicht und habe sie gerade zu den Schaltflächenunteransichten hinzugefügt:

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

Dies wurde von Karim oben inspiriert.

David H.
quelle
Sie könnten einfach UIVIew verwenden. UIView * line = [[UIView-Zuweisung] initWithFrame: frame]; line.backgroundColor = [UIColor lightGrayColor];
Dzeikei
0

Basierend auf den Antworten von Kovpas & Damien Praca finden Sie hier eine Implementierung von UILabelUnderligned, die auch textAlignemnt unterstützt .

#import <UIKit/UIKit.h>

@interface UILabelUnderlined : UILabel

@end

und die Umsetzung:

#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
Pascal
quelle
Update für iOS 6 für switch: switch (self.textAlignment) {case NSTextAlignmentLeft: case NSTextAlignmentJustified: case NSTextAlignmentNatural: break; case NSTextAlignmentCenter: alignementXOffset = (self.titleLabel.frame.size.width - textSize.width) / 2; brechen; case NSTextAlignmentRight: alignementXOffset = self.titleLabel.frame.size.width - textSize.width; brechen; }
pfrank
0

Hier ist eine andere, einfachere Lösung (die Breite der Unterstreichung ist nicht genau, aber für mich gut genug)

Ich habe eine UIView mit weißem (_view_underline)Hintergrund und einer Höhe von 1 Pixel und aktualisiere ihre Breite jedes Mal, wenn ich den Text aktualisiere

// 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];
}
Ege Akpinar
quelle
0

NSUnderlineStyleAttributeName, der eine NSNumber (wobei 0 keine Unterstreichung ist) verwendet, kann einem Attributwörterbuch hinzugefügt werden. Ich weiß nicht, ob das einfacher ist. Aber für meine Zwecke war es einfacher.

    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];
epaus
quelle
0

Swift 4.1 ver:

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

label.attributedText = underlineAttriString
Abdoelrhman
quelle
0

Sie können dies mein benutzerdefiniertes Etikett verwenden! Sie können den Interface Builder auch zum Festlegen verwenden

import UIKit


class  YHYAttributedLabel : UILabel{
    
    
    @IBInspectable
    var underlineText : String = ""{
        
        didSet{

            self.attributedText = NSAttributedString(string: underlineText,
            attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
        }
        
        
    }

}
Ucdemir
quelle