92

複数行の文字列になる可能性のあるテキストに下線を引くにはどうすればよいですか? UIWebView を提案する人もいますが、テキスト レンダリングだけでは明らかに重すぎるクラスです。

私の考えは、各行の各文字列の開始点と長さを把握することでした. それに応じてその下に線を引きます。

文字列の長さと開始点をどのように把握するかで問題が発生します。

を使用しようとしましたが-[UILabel textRectForBounds:limitedToNumberOfLines:]、これはテキストの境界矩形を描画する必要がありますか? それから私はアライメントに取り組む必要がありますか?中央揃えで右揃えの場合、各行の開始点を取得するにはどうすればよいですか?

4

21 に答える 21

136

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 は UILabel の NSAttributedString サポートを追加したため、はるかに簡単になり、複数の行で機能します。

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

それでも iOS 4 と iOS 5 をサポートしたい場合は、手動でラベルに下線を引くのではなく、TTTAttributedLabelを使用することをお勧めします。ただし、1 行の UILabel に下線を引く必要があり、サードパーティのコンポーネントを使用したくない場合でも、上記のコードでうまくいきます。

于 2010-04-26T06:59:05.557 に答える
54

スウィフトの場合:

let underlineAttriString = NSAttributedString(string: "attriString",
                                          attributes: [NSAttributedString.Key.underlineStyle: NSUnderlineStyle.single.rawValue])
label.attributedText = underlineAttriString
于 2014-11-22T08:51:33.797 に答える
38

これが私がしたことです。バターのように機能します。

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];
于 2013-10-28T08:47:46.600 に答える
19

属性文字列を使用します。

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

または、オーバーライドする代わりに、Olivier Halligon によって作成されたOHAttributedLabelを使用することをお勧めします。

于 2012-04-11T12:08:00.557 に答える
15

提供された回答のいくつかを組み合わせて、(少なくとも私の要件では)より優れた UILabel サブクラスを作成しました。これは、以下をサポートします。

  • さまざまなラベル境界を持つマルチ テキスト (テキストはラベル フレームの中央または正確なサイズにすることができます)
  • 下線
  • 三振
  • 下線/取り消し線のオフセット
  • テキストの配置
  • 異なるフォントサイズ

https://github.com/GuntisTreulands/UnderLineLabel

于 2012-08-06T10:56:11.767 に答える
11

ビュー (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];
}
于 2011-01-11T15:36:21.673 に答える
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;
}
于 2013-02-20T08:43:11.447 に答える
7
NSMutableAttributedString *text = [self.myUILabel.attributedText mutableCopy];
[text addAttribute:NSUnderlineStyleAttributeName value:@(NSUnderlineStyleSingle) range:NSMakeRange(0, text.length)];
self.myUILabel.attributedText = text;
于 2016-04-11T13:38:59.747 に答える
7

別の解決策は (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)}];

これが役立つことを願っています;-)

于 2015-04-21T17:14:44.447 に答える
1

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
于 2011-05-19T13:04:20.067 に答える
1

下線付きの複数行の 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]; 
}
于 2011-08-25T07:32:26.553 に答える
0

kovpas が示したように、ほとんどの場合に境界ボックスを使用できますが、境界ボックスがテキストの周りにきちんと収まるとは限りません。UILabel の設定によっては、高さが 50 でフォント サイズが 12 のボックスでは、必要な結果が得られない場合があります。

UILabel 内の UIString をクエリして正確なメトリックを決定し、これらを使用して、kovpas によって既に提供されている描画コードを使用して、囲んでいる境界ボックスまたはフレームに関係なく、下線を適切に配置します。

また、特定のフォントに基づいてベースライン間の距離を示す UIFont の "leading" プロパティも確認する必要があります。ベースラインは、下線を引きたい場所です。

NSString への UIKit の追加を調べます。

(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.
于 2010-04-26T07:34:23.347 に答える
0

これが別のより簡単な解決策です(下線の幅は最も正確ではありませんが、私にとっては十分でした)

白い背景、高さ 1 ピクセルの UIView(_view_underline)があり、テキストを更新するたびに幅を更新します

// 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];
}
于 2012-11-14T09:29:27.133 に答える
0

私はオープン ソースのライン ビューを使用し、それをボタンのサブビューに追加しました。

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

これは、上記のカリムに触発されました。

于 2011-10-07T18:40:32.357 に答える
0

このマイカスタムラベルが使えます!インターフェイスビルダーを使用して設定することもできます

import UIKit


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

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

}
于 2020-08-13T23:45:15.557 に答える