2286

UILabel2行のテキスト用のスペースがあります。テキストが短すぎる場合、このテキストはラベルの垂直方向の中央に表示されることがあります。

テキストを常に上部に配置するにはどうすればよいUILabelですか?

垂直方向に中央揃えのテキストを持つ UILabel を表す画像

4

51 に答える 51

339
  1. 新しいテキストを設定します。

    myLabel.text = @"Some Text"
    
  2. maximum number行数を 0 (自動) に設定します。

    myLabel.numberOfLines = 0
    
  3. ラベルのフレームを最大サイズに設定します。

    myLabel.frame = CGRectMake(20,20,200,800)
    
  4. sizeToFitフレーム サイズを小さくしてコンテンツがちょうど収まるように呼び出します。

    [myLabel sizeToFit]
    

ラベル フレームは、テキストに合わせて十分な高さと幅になりました。左上は変わらないはずです。左上揃えのテキストでのみこれをテストしました。他の位置合わせについては、後でフレームを変更する必要がある場合があります。

また、ラベルでワードラップが有効になっています。

于 2010-08-27T16:24:34.260 に答える
162

拡張ソリューションを参照してください:

for(int i=1; i< newLinesToPad; i++) 
    self.text = [self.text stringByAppendingString:@"\n"];

に置き換える必要があります

for(int i=0; i<newLinesToPad; i++)
    self.text = [self.text stringByAppendingString:@"\n "];

UILabelsiPhoneの末尾の改行は無視されるように見えるため、追加されたすべての改行に追加のスペースが必要です:(

同様に、alignBottom も@" \n@%"in の代わりに更新"\n@%"する必要があります (for サイクルの初期化も "for(int i=0..." に置き換える必要があります)。

次の拡張機能が機能します。

// -- file: UILabel+VerticalAlign.h
#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end

// -- file: UILabel+VerticalAlign.m
@implementation UILabel (VerticalAlign)
- (void)alignTop {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [self.text stringByAppendingString:@"\n "];
}

- (void)alignBottom {
    CGSize fontSize = [self.text sizeWithFont:self.font];
    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label
    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];
    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;
    for(int i=0; i<newLinesToPad; i++)
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
}
@end

次に、各 yourLabel テキスト割り当ての後に[yourLabel alignTop];orを呼び出します。[yourLabel alignBottom];

于 2010-09-09T13:01:44.130 に答える
160

Just in case it's of any help to anyone, I had the same problem but was able to solve the issue simply by switching from using UILabel to using UITextView. I appreciate this isn't for everyone because the functionality is a bit different.

If you do switch to using UITextView, you can turn off all the Scroll View properties as well as User Interaction Enabled... This will force it to act more like a label.

enter image description here

于 2011-10-05T12:46:48.703 に答える
138

大騒ぎする必要はありません

@interface MFTopAlignedLabel : UILabel

@end


@implementation MFTopAlignedLabel

- (void)drawTextInRect:(CGRect) rect
{
    NSAttributedString *attributedText = [[NSAttributedString alloc]     initWithString:self.text attributes:@{NSFontAttributeName:self.font}];
    rect.size.height = [attributedText boundingRectWithSize:rect.size
                                            options:NSStringDrawingUsesLineFragmentOrigin
                                            context:nil].size.height;
    if (self.numberOfLines != 0) {
        rect.size.height = MIN(rect.size.height, self.numberOfLines * self.font.lineHeight);
    }
    [super drawTextInRect:rect];
}

@end

むちゃくちゃ、Objective-c、大騒ぎはありませんが、Swift 3:

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSFontAttributeName: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}

スウィフト 4.2

class VerticalTopAlignLabel: UILabel {

    override func drawText(in rect:CGRect) {
        guard let labelText = text else {  return super.drawText(in: rect) }

        let attributedText = NSAttributedString(string: labelText, attributes: [NSAttributedString.Key.font: font])
        var newRect = rect
        newRect.size.height = attributedText.boundingRect(with: rect.size, options: .usesLineFragmentOrigin, context: nil).size.height

        if numberOfLines != 0 {
            newRect.size.height = min(newRect.size.height, CGFloat(numberOfLines) * font.lineHeight)
        }

        super.drawText(in: newRect)
    }

}
于 2012-05-21T07:47:43.957 に答える
82

上記の答えのように、しかし、それは完全に正しくないか、コードに平手打ちするのが簡単ではないため、少しクリーンアップしました. この拡張子を独自の .h および .m ファイルに追加するか、使用する実装のすぐ上に貼り付けます。

#pragma mark VerticalAlign
@interface UILabel (VerticalAlign)
- (void)alignTop;
- (void)alignBottom;
@end


@implementation UILabel (VerticalAlign)
- (void)alignTop
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i<= newLinesToPad; i++)
    {
        self.text = [self.text stringByAppendingString:@" \n"];
    }
}

- (void)alignBottom
{
    CGSize fontSize = [self.text sizeWithFont:self.font];

    double finalHeight = fontSize.height * self.numberOfLines;
    double finalWidth = self.frame.size.width;    //expected width of label


    CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];


    int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

    for(int i=0; i< newLinesToPad; i++)
    {
        self.text = [NSString stringWithFormat:@" \n%@",self.text];
    }
}
@end

そして使用するには、テキストをラベルに入れ、適切なメソッドを呼び出して整列させます。

[myLabel alignTop];

また

[myLabel alignBottom];
于 2010-03-04T02:44:37.183 に答える
71

これを実現するためのさらに迅速な (そして汚い) 方法は、UILabel の改行モードを「クリップ」に設定し、一定量の改行を追加することです。

myLabel.lineBreakMode = UILineBreakModeClip;
myLabel.text = [displayString stringByAppendingString:"\n\n\n\n"];

この解決策はすべての人に有効というわけではありません。特に、表示している行数を超えても文字列の最後に「...」を表示したい場合は、次のいずれかを使用する必要があります。コードのビットが長くなりますが、多くの場合、これで必要なものが得られます。

于 2010-04-18T21:08:23.447 に答える
63

代わりに、垂直方向の配置オプションを持つ which をUILabel使用できます。UITextField

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction
于 2012-02-10T10:36:41.527 に答える
53

私は長い間これに苦労してきました、そして私は私の解決策を共有したかったです。

これにより、UILabelテキストを0.5スケールまで自動縮小し、テキストを垂直方向に中央揃えにすることができます。これらのオプションは、ストーリーボード/IBでも使用できます。

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
于 2012-10-16T16:38:02.057 に答える
46

新しいクラスを作成する

ラベル上揃え

.h ファイル

#import <UIKit/UIKit.h>


@interface KwLabelTopAlign : UILabel {

}

@end

.m ファイル

#import "KwLabelTopAlign.h"


@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect {
    int lineHeight = [@"IglL" sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, 9999.0f)].height;
    if(rect.size.height >= lineHeight) {
        int textHeight = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(rect.size.width, rect.size.height)].height;
        int yMax = textHeight;
        if (self.numberOfLines > 0) {
            yMax = MIN(lineHeight*self.numberOfLines, yMax);    
        }

        [super drawTextInRect:CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, yMax)];
    }
}

@end

編集

同じことを行うより単純な実装を次に示します。

#import "KwLabelTopAlign.h"

@implementation KwLabelTopAlign

- (void)drawTextInRect:(CGRect)rect
{
    CGFloat height = [self.text sizeWithFont:self.font
                            constrainedToSize:rect.size
                                lineBreakMode:self.lineBreakMode].height;
    if (self.numberOfLines != 0) {
        height = MIN(height, self.font.lineHeight * self.numberOfLines);
    }
    rect.size.height = MIN(rect.size.height, height);
    [super drawTextInRect:rect];
}

@end
于 2011-08-04T08:07:29.257 に答える
41

ここに画像の説明を入力してください

InterfaceBuilderで

  • UILabel可能な限り最大のテキストのサイズに設定
  • Lines属性インスペクターで「0」に設定

あなたのコードで

  • ラベルのテキストを設定します
  • sizeToFitあなたのレーベルに電話してください

コードスニペット:

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];
于 2012-01-03T04:40:41.947 に答える
35

UILabelのサブクラスを作成します。魅力のように機能します:

// TopLeftLabel.h

#import <Foundation/Foundation.h>

@interface TopLeftLabel : UILabel 
{
}

@end

// TopLeftLabel.m

#import "TopLeftLabel.h"

@implementation TopLeftLabel

- (id)initWithFrame:(CGRect)frame 
{
    return [super initWithFrame:frame];
}

- (CGRect)textRectForBounds:(CGRect)bounds limitedToNumberOfLines:(NSInteger)numberOfLines 
{
    CGRect textRect = [super textRectForBounds:bounds limitedToNumberOfLines:numberOfLines];    
    textRect.origin.y = bounds.origin.y;
    return textRect;
}

-(void)drawTextInRect:(CGRect)requestedRect 
{
    CGRect actualRect = [self textRectForBounds:requestedRect limitedToNumberOfLines:self.numberOfLines];
    [super drawTextInRect:actualRect];
}

@end

ここで説明したように。

于 2011-07-14T14:33:10.467 に答える
29

この目的を達成するために util 関数を作成しました。あなたは見てみることができます:

// 複数行のラベルの高さを調整して、垂直に上に揃えます
+ (void) alignLabelWithTop:(UILabel *)ラベル {
  CGSize maxSize = CGSizeMake(label.frame.size.width, 999);
  label.adjustsFontSizeToFitWidth = NO;

  // 実際の高さを取得
  CGSize actualSize = [label.text sizeWithFont:label.font constraintToSize:maxSize lineBreakMode:label.lineBreakMode];
  CGRect rect = label.frame;
  rect.size.height = actualSize.height;
  label.frame = rect;
}

。使い方?(lblHello が Interface builder によって作成された場合、UILabel 属性の詳細をいくつかスキップします)

lblHello.text = @"Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World! Hello World!";
lblHello.numberOfLines = 5;
[ユーティリティ alignLabelWithTop:lblHello];

記事としてブログにも書きました: http://fstoke.me/blog/?p=2819

于 2011-05-23T08:16:32.333 に答える
27

コードと紹介ページのコードを読むのに少し時間がかかりましたが、デフォルトの中央の垂直方向の配置が表示されないように、すべてがラベルのフレームサイズを変更しようとしていることがわかりました。

ただし、場合によっては、ラベルに大量のテキストが含まれている場合でも(たとえば、同じ高さの複数の行)、ラベルがこれらすべてのスペースを占めるようにしたい場合があります。

ここでは、ラベルの最後に改行を埋め込むだけで、別の方法で問題を解決しました(plsはUILabel、実際にはを継承していることに注意してくださいが、必須ではありません)。

CGSize fontSize = [self.text sizeWithFont:self.font];

finalHeight = fontSize.height * self.numberOfLines;
finalWidth = size.width;    //expected width of label

CGSize theStringSize = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(finalWidth, finalHeight) lineBreakMode:self.lineBreakMode];

int newLinesToPad = (finalHeight  - theStringSize.height) / fontSize.height;

for(int i = 0; i < newLinesToPad; i++)
{
    self.text = [self.text stringByAppendingString:@"\n "];
}
于 2010-01-30T06:32:33.127 に答える
27

を使用しtextRect(forBounds:limitedToNumberOfLines:)ます。

class TopAlignedLabel: UILabel {
  override func drawText(in rect: CGRect) {
    let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
    super.drawText(in: textRect)
  }
}
于 2016-12-28T18:45:20.940 に答える
20

ここでの提案を参考にして、UILabel をラップできるビューを作成し、サイズを変更して行数を設定し、上揃えにします。UILabel をサブビューとして配置するだけです。

@interface TopAlignedLabelContainer : UIView
{
}

@end

@implementation TopAlignedLabelContainer

- (void)layoutSubviews
{
    CGRect bounds = self.bounds;

    for (UILabel *label in [self subviews])
    {
        if ([label isKindOfClass:[UILabel class]])
        {
            CGSize fontSize = [label.text sizeWithFont:label.font];

            CGSize textSize = [label.text sizeWithFont:label.font
                                     constrainedToSize:bounds.size
                                         lineBreakMode:label.lineBreakMode];

            label.numberOfLines = textSize.height / fontSize.height;

            label.frame = CGRectMake(0, 0, textSize.width,
                 fontSize.height * label.numberOfLines);
        }
    }
}

@end
于 2010-12-14T01:27:52.477 に答える
20

TTTAttributedLabelを使用できます。垂直方向の配置がサポートされています。

@property (nonatomic) TTTAttributedLabel* label;
<...>

//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;
于 2014-08-28T08:50:55.340 に答える
16

私は上記の多くの方法を使用してきましたが、私が使用した手っ取り早いアプローチを追加したいだけです:

myLabel.text = [NSString stringWithFormat:@"%@\n\n\n\n\n\n\n\n\n",@"My label text string"];

文字列内の改行の数によって、使用可能な垂直方向のスペースがテキストで埋められることを確認し、UILabel を設定してオーバーフローしたテキストを切り捨てます。

時には十分で十分だからです。

于 2012-09-18T15:59:57.627 に答える
14

複数行、最小フォントサイズ、および親ビューの水平方向と垂直方向の両方に配置できるラベルが必要でした。プログラムでビューにラベルを追加しました。

- (void) customInit {
    // Setup label
    self.label = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
    self.label.numberOfLines = 0;
    self.label.lineBreakMode = UILineBreakModeWordWrap;
    self.label.textAlignment = UITextAlignmentCenter;

    // Add the label as a subview
    self.autoresizesSubviews = YES;
    [self addSubview:self.label];
}

そして、ラベルのテキストを変更したいとき...

- (void) updateDisplay:(NSString *)text {
    if (![text isEqualToString:self.label.text]) {
        // Calculate the font size to use (save to label's font)
        CGSize textConstrainedSize = CGSizeMake(self.frame.size.width, INT_MAX);
        self.label.font = [UIFont systemFontOfSize:TICKER_FONT_SIZE];
        CGSize textSize = [text sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        while (textSize.height > self.frame.size.height && self.label.font.pointSize > TICKER_MINIMUM_FONT_SIZE) {
            self.label.font = [UIFont systemFontOfSize:self.label.font.pointSize-1];
            textSize = [ticker.blurb sizeWithFont:self.label.font constrainedToSize:textConstrainedSize];
        }
        // In cases where the frame is still too large (when we're exceeding minimum font size),
        // use the views size
        if (textSize.height > self.frame.size.height) {
            textSize = [text sizeWithFont:self.label.font constrainedToSize:self.frame.size];
        }

        // Draw 
        self.label.frame = CGRectMake(0, self.frame.size.height/2 - textSize.height/2, self.frame.size.width, textSize.height);
        self.label.text = text;
    }
    [self setNeedsDisplay];
}

それが誰かを助けることを願っています!

于 2010-09-14T01:14:58.400 に答える
14

FXLabel (github 上)は、 に設定label.contentModeすることで、すぐに使用できUIViewContentModeTopます。このコンポーネントは私が作成したものではありませんが、私が頻繁に使用するコンポーネントであり、多くの機能があり、うまく機能しているようです。

于 2013-09-27T15:35:55.560 に答える
11

ラベル内のテキストが垂直方向の中央に配置されていないため、これを読んでいる人は、一部のフォント タイプが同じように設計されていないことに注意してください。たとえば、zapfino サイズ 16 のラベルを作成すると、テキストが垂直方向に完全に中央揃えされていないことがわかります。

ただし、ヘルベチカを使用すると、テキストが垂直方向に中央揃えになります。

于 2011-03-01T00:09:24.623 に答える
10

自動レイアウトを使用している場合は、コードまたは IB のいずれかで垂直方向の contentHuggingPriority を 1000 に設定します。IB では、優先度を 1 に設定してから削除することにより、高さの制約を削除する必要がある場合があります。

于 2013-09-05T16:38:17.933 に答える
10

UILabel をサブクラス化し、次のように描画長方形を制約します。

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];
    rect.size.height = MIN(rect.size.height, sizeThatFits.height);

    [super drawTextInRect:rect];
}

改行パディングを含む解決策を試してみましたが、場合によっては正しくない動作に遭遇しました。私の経験では、上記のように描画 rect を制約する方が、 をいじるよりも簡単numberOfLinesです。

PS この方法で UIViewContentMode をサポートすることは簡単に想像できます。

- (void)drawTextInRect:(CGRect)rect
{
    CGSize sizeThatFits = [self sizeThatFits:rect.size];

    if (self.contentMode == UIViewContentModeTop) {
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }
    else if (self.contentMode == UIViewContentModeBottom) {
        rect.origin.y = MAX(0, rect.size.height - sizeThatFits.height);
        rect.size.height = MIN(rect.size.height, sizeThatFits.height);
    }

    [super drawTextInRect:rect];
}
于 2012-07-03T15:49:29.110 に答える
8

あっという間に、

let myLabel : UILabel!

ラベルのテキストを画面に合わせて上部に配置するには

myLabel.sizeToFit()

ラベルのフォントを画面の幅または特定の幅のサイズに合わせます。

myLabel.adjustsFontSizeToFitWidth = YES

および label の textAlignment :

myLabel.textAlignment = .center

myLabel.textAlignment = .left

myLabel.textAlignment = .right

myLabel.textAlignment = .Natural

myLabel.textAlignment = .Justified

于 2016-02-23T02:27:14.967 に答える
8

複雑なタスクを実行していない限り、UITextView代わりに を使用できますUILabels

スクロールを無効にします。

テキストを完全に表示したい場合は、ユーザーsizeToFitsizeThatFits:メソッドだけ

于 2012-03-12T18:37:06.287 に答える
7

これは古い解決策です。iOS >= 6 で autolayout を使用してください

私の解決策:

  1. 自分で行を分割 (ラベルの折り返し設定を無視)
  2. 自分で線を引く(ラベルの配置は無視)

@interface UITopAlignedLabel : UILabel

@end

@implementation UITopAlignedLabel

#pragma mark Instance methods

- (NSArray*)splitTextToLines:(NSUInteger)maxLines {
    float width = self.frame.size.width;

    NSArray* words = [self.text componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
    NSMutableArray* lines = [NSMutableArray array];

    NSMutableString* buffer = [NSMutableString string];    
    NSMutableString* currentLine = [NSMutableString string];

    for (NSString* word in words) {
        if ([buffer length] > 0) {
            [buffer appendString:@" "];
        }

        [buffer appendString:word];

        if (maxLines > 0 && [lines count] == maxLines - 1) {
            [currentLine setString:buffer];
            continue;
        }

        float bufferWidth = [buffer sizeWithFont:self.font].width;

        if (bufferWidth < width) {
            [currentLine setString:buffer];
        }
        else {
            [lines addObject:[NSString stringWithString:currentLine]];

            [buffer setString:word];
            [currentLine setString:buffer];
        }
    }

    if ([currentLine length] > 0) {
        [lines addObject:[NSString stringWithString:currentLine]];
    }

    return lines;
}

- (void)drawRect:(CGRect)rect {
    if ([self.text length] == 0) {
        return;
    }

    CGContextRef context = UIGraphicsGetCurrentContext();

    CGContextSetFillColorWithColor(context, self.textColor.CGColor);
    CGContextSetShadowWithColor(context, self.shadowOffset, 0.0f, self.shadowColor.CGColor);

    NSArray* lines = [self splitTextToLines:self.numberOfLines];
    NSUInteger numLines = [lines count];

    CGSize size = self.frame.size;
    CGPoint origin = CGPointMake(0.0f, 0.0f);

    for (NSUInteger i = 0; i < numLines; i++) {
        NSString* line = [lines objectAtIndex:i];

        if (i == numLines - 1) {
            [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeTailTruncation];            
        }
        else {
            [line drawAtPoint:origin forWidth:size.width withFont:self.font lineBreakMode:UILineBreakModeClip];
        }

        origin.y += self.font.lineHeight;

        if (origin.y >= size.height) {
            return;
        }
    }
}

@end
于 2011-09-28T11:46:03.557 に答える
6

独自のカスタム ビューを作成するオプションがある場合は、次のようにすることができます。

- (void)drawRect:(CGRect)rect
{
    CGRect bounds = self.bounds;
    [self.textColor set];
    [self.text drawInRect:bounds
                 withFont:self.font
            lineBreakMode:UILineBreakModeTailTruncation
                alignment:self.textAlignment];
}
于 2011-08-16T21:43:10.207 に答える
6

これが古い投稿であることは知っていますが、テキストを垂直方向に配置することは大きな問題です (少なくとも私にとってはそうです)。

私の意見では、 drawRect の使用は少し高価です。UILabel を垂直方向に整列させる適切な方法は、UILabel を使用しないことです。UITextView (複数行の UITextField) を使用し、コンテンツ プロパティを次のように観察します。

- (UITextView*)textView{
     if(!_textView){
        UIEdgeInsets insets = UIEdgeInsetsMake(0, 50, 0, 5);
        CGRect frame = CGRectMake(0.0f, 0.0f, 100.0f, 100.0f);
        _textView = [[UITextView alloc]initWithFrame:UIEdgeInsetsInsetRect(frame, insets)];
        _textView.delegate = self;
        _textView.scrollEnabled = YES;
        _textView.bounces = YES;
        _textView.backgroundColor = [UIColor whiteColor];
        [_textView setUserInteractionEnabled:NO];
        [_textView addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
    }
    return _textView;
}

 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:    (NSDictionary *)change context:(void *)context {
UITextView *tv = object;

CGFloat height = [tv bounds].size.height;
CGFloat contentheight;

#ifdef __IPHONE_7_0
    contentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height;
#else
    contentheight = [tv contentSize].height;
#endif

    switch(self.verticalAlignment) {
        case VerticalAlignmentBottom:{
            CGFloat topCorrect = ([tv bounds].size.height - contentheight);
            topCorrect = (topCorrect <0.0 ? 0.0 : topCorrect);
            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
        }
        break;
        case VerticalAlignmentMiddle:{
            CGFloat topCorrect = (height - contentheight * [tv zoomScale])/2.0;
            topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
            tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
        }
            break;
        case VerticalAlignmentTop:{
            tv.contentOffset = (CGPoint){.x = 0, .y = 0 };
        }
            break;
        default:
            break;
    }
}

基本的にここで起こっていることは、私たちがいるクラスをオブザーバーとして設定し、NSKeyValueObservingOptionNew のオプションで contentSize プロパティを見て、コンテンツが変更されるたび-(void)observeValueForKeyPath:ofObject:change:context:に呼び出され、オフセット サイズを計算してテキストを適切に揃えることです。 .

これを信用することはできません。元のアイデアはここから生まれました。ただし、このソリューションは iOS7 では機能しません。SOを数時間トロールした後、これを見つけました:iOS 7の垂直方向の配置の修正。キーラインはcontentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height;. iOS 7 では、何らかの理由で contentSize の高さを取得できませんが、修正されています。2 つの解決策はどちらも単独では機能しませんでしたが、少しいじった後、上記の解決策を合成することができました。

于 2013-12-13T03:25:42.017 に答える
6

UILabel では、垂直方向のテキストの配置はできません。sizeWithFont:ただし、 のメソッドを使用してラベルの高さを動的に変更し、NSString必要に応じて x と y を設定することができます。

使用できますUITextField。のサブクラスであるため、 contentVerticalAlignment peopertyをサポートしUIControlます。userInteractionEnabledユーザーがテキストを入力できないようにするには、NO に設定する必要があります。

于 2012-05-16T06:47:31.130 に答える
6

スイフト3の場合...

@IBDesignable class TopAlignedLabel: UILabel {
    override func drawText(in rect: CGRect) {
        if let stringText = text {
            let stringTextAsNSString = stringText as NSString
            let labelStringSize = stringTextAsNSString.boundingRect(with: CGSize(width: self.frame.width,height: CGFloat.greatestFiniteMagnitude),
                                                                            options: NSStringDrawingOptions.usesLineFragmentOrigin,
                                                                            attributes: [NSFontAttributeName: font],
                                                                            context: nil).size
            super.drawText(in: CGRect(x:0,y: 0,width: self.frame.width, height:ceil(labelStringSize.height)))
        } else {
            super.drawText(in: rect)
        }
    }
    override func prepareForInterfaceBuilder() {
        super.prepareForInterfaceBuilder()
        layer.borderWidth = 1
        layer.borderColor = UIColor.black.cgColor
    }
}
于 2016-10-25T09:37:21.777 に答える
6

スウィフト 2.0:

空の Swift ファイルで定数列挙値を作成します。

//  AppRef.swift

import UIKit
import Foundation

enum UILabelTextPositions : String {

 case VERTICAL_ALIGNMENT_TOP = "VerticalAlignmentTop"
 case VERTICAL_ALIGNMENT_MIDDLE = "VerticalAlignmentMiddle"
 case VERTICAL_ALIGNMENT_BOTTOM = "VerticalAlignmentBottom"

}

UILabel 拡張機能の使用:

空の Swift クラスを作成し、名前を付けます。以下を追加

//  AppExtensions.swift

import Foundation
import UIKit

extension UILabel{ 
 func makeLabelTextPosition (sampleLabel :UILabel?, positionIdentifier : String) -> UILabel
 {
  let rect = sampleLabel!.textRectForBounds(bounds, limitedToNumberOfLines: 0)

  switch positionIdentifier
  {
  case "VerticalAlignmentTop":
   sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y, rect.size.width, rect.size.height)
   break;

  case "VerticalAlignmentMiddle":
   sampleLabel!.frame = CGRectMake(bounds.origin.x+5,bounds.origin.y + (bounds.size.height - rect.size.height) / 2,
    rect.size.width, rect.size.height);
   break;

  case "VerticalAlignmentBottom":
   sampleLabel!.frame = CGRectMake(bounds.origin.x+5, bounds.origin.y + (bounds.size.height - rect.size.height),rect.size.width, rect.size.height);
   break;

  default:
   sampleLabel!.frame = bounds;
   break;
  }
  return sampleLabel!

 }
}

使用法 :

myMessageLabel.makeLabelTextPosition(messageLabel, positionIdentifier: UILabelTextPositions.VERTICAL_ALIGNMENT_TOP.rawValue)
于 2016-03-29T06:16:56.567 に答える
5

私はその特定の問題にも取り組んでいたので、DSnevan kingのアイデアを取り入れ、基本的にそれらを垂直方向の配置プロパティを実装するサブクラスにまとめました。これにより、配置を複数回変更することもできます。型を借りてUIControlContentVerticalAlignmentにも対応していますUIControlContentVerticalAlignmentFill

私が見numberOfLinesたところ、垂直方向の配置に関しては役に立たないように思われるため、このサブクラスでは、垂直方向の配置を適用するときに常に0に設定されています。また、lineBreakMode複数行のテキスト ラベルが必要な場合に備えて、自分で設定する必要があります。

そこにあります:GitHubのQALabel

于 2012-04-10T09:14:34.660 に答える
5

私は dalewking の提案を参考にし、UIEdgeInset を追加してマージンを調整できるようにしました。良い回避策。

- (id)init
{
    if (self = [super init]) {
        contentEdgeInsets = UIEdgeInsetsZero;
    }

    return self;
}

- (void)layoutSubviews
{
    CGRect localBounds = self.bounds;
    localBounds = CGRectMake(MAX(0, localBounds.origin.x + contentEdgeInsets.left), 
                             MAX(0, localBounds.origin.y + contentEdgeInsets.top), 
                             MIN(localBounds.size.width, localBounds.size.width - (contentEdgeInsets.left + contentEdgeInsets.right)), 
                             MIN(localBounds.size.height, localBounds.size.height - (contentEdgeInsets.top + contentEdgeInsets.bottom)));

    for (UIView *subview in self.subviews) {
        if ([subview isKindOfClass:[UILabel class]]) {
            UILabel *label = (UILabel*)subview;
            CGSize lineSize = [label.text sizeWithFont:label.font];
            CGSize sizeForText = [label.text sizeWithFont:label.font constrainedToSize:localBounds.size lineBreakMode:label.lineBreakMode];

            NSInteger numberOfLines = ceilf(sizeForText.height/lineSize.height);

            label.numberOfLines = numberOfLines;
            label.frame = CGRectMake(MAX(0, contentEdgeInsets.left), MAX(0, contentEdgeInsets.top), localBounds.size.width, MIN(localBounds.size.height, lineSize.height * numberOfLines)); 
        }
    }
}
于 2010-12-15T19:41:23.397 に答える
4

この問題を解決しようとしているカスタム テーブル セルを使用している場合は、これをカスタム テーブル セル クラスに追加します。

スウィフト 2.2:

override func layoutSubviews() {
    labelName.sizeToFit()
}

これで私の問題は解決しました。

于 2016-06-14T06:24:34.013 に答える
4

この問題を解決するには 2 つの方法があります。

[mylabel setNumberOfLines:0];
[mylabel sizeToFit];

しかし、このアプローチでは 2 番目の方法の方が信頼性が高くなります。つまり、

 CGSize sizeToFit = [label.text sizeWithFont:label.font constrainedToSize:maxSize lineBreakMode:label.lineBreakMode];
 [mylabel setFrame:CGRectMake(mylabel.frame.origin.x, mylabel.frame.origin.y, sizeToFit.width, sizeToFit.height)];

「\n」と入力するのはあまり良いことではありませんが、表示されるデータの制約とサイズがわかっている場合は、うまく機能するかもしれませんが、テキストがラベルのサイズよりも長い場合は拡張できません。2 番目の方法では、最終的に表示されるテキストのサイズに応じてフレームを設定します。

于 2012-10-02T06:36:37.377 に答える
3

を使用する代わりにsizeToFit、ラベルの高さを手動で変更できます。

CGSize size = [descLabel.text sizeWithFont:descLabel.font constrainedToSize:CGSizeMake(labelWidth, labelHeight)];
CGRect frame = descLabel.frame;
frame.size.height = size.height;    
[yourLabel setFrame:frame];

返されるサイズは、ラベルの内容に最適です。ラベルの高さがそのコンテンツに適合している場合、コンテンツがラベルの中央に配置されても問題はありません。

于 2013-03-15T04:52:08.333 に答える
3

このコードは、テキストを上に揃え、ラベルの高さをテキスト コンテンツに固定するのに役立ちます。

以下のコードを使用するための指示

isHeightToChangeデフォルトでは true で、ラベルの高さがテキスト コンテンツと自動的に同じになります。 isHeightToChangefalse の場合、ラベルの高さを減らさずにテキストを上に揃えます。

#import "DynamicHeightLable.h"

@implementation DynamicHeightLable
@synthesize isHeightToChange;
- (id)initWithFrame:(CGRect)frame 
{
    self = [super initWithFrame:frame];
    if (self)
    {
        // Initialization code.
        self.isHeightToChange=FALSE;//default

    }
    return self;
}
- (void)drawTextInRect:(CGRect)rect
{
    if(!isHeightToChange){
    CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);

    CGFloat height = [self.text sizeWithFont:self.font
                           constrainedToSize:maximumLabelSize
                               lineBreakMode:self.lineBreakMode].height;
    if (self.numberOfLines != 0) {
        height = MIN(height, self.font.lineHeight * self.numberOfLines);
    }
    rect.size.height = MIN(rect.size.height, height);
    }
    [super drawTextInRect:rect];

}
- (void) layoutSubviews
{
    [super layoutSubviews];
       if(isHeightToChange){
     CGRect ltempFrame = self.frame;
    CGSize maximumLabelSize = CGSizeMake(self.frame.size.width,2500);

    CGFloat height = [self.text sizeWithFont:self.font
                           constrainedToSize:maximumLabelSize
                               lineBreakMode:self.lineBreakMode].height;
    if (self.numberOfLines != 0) {
        height = MIN(height, self.font.lineHeight * self.numberOfLines);
    }
    ltempFrame.size.height = MIN(ltempFrame.size.height, height);

    ltempFrame.size.height=ltempFrame.size.height;
    self.frame=ltempFrame;
       }
}
@end
于 2013-03-25T06:26:57.047 に答える
2

投稿された他のすべてのソリューションに基づいて、配置プロパティを設定するときに垂直方向の配置を処理する単純な小さなUILabelサブクラスを作成しました。これにより、向きの変更時にもラベルが更新され、テキストの高さが制限され、ラベルの幅が元のサイズに保たれます。

.h

@interface VAlignLabel : UILabel
@property (nonatomic, assign) WBZVerticalAlignment alignment;
@end


.m

 -(void)setAlignment:(WBZVerticalAlignment)alignment{

    _alignment = alignment;

    CGSize s = [self.text sizeWithFont:self.font constrainedToSize:CGSizeMake(self.frame.size.width, 9999) lineBreakMode:NSLineBreakByWordWrapping];

    switch (_alignment)
    {
        case wbzLabelAlignmentVerticallyTop:
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y, self.frame.size.width, s.height);
            break;
        case wbzLabelAlignmentVerticallyMiddle:
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y + (self.frame.size.height - s.height)/2, self.frame.size.width, s.height);
            break;
        case wbzLabelAlignmentVerticallyBottom:
            self.frame = CGRectMake(self.frame.origin.x, self.frame.origin.y + (self.frame.size.height - s.height), self.frame.size.width, s.height);
            break;
        default:
            break;
    }
}

-(void)layoutSubviews{
    [self setAlignment:self.alignment];
}
于 2013-01-31T11:29:19.577 に答える
0

height constraintInterface Builder でラベルに a を設定し、IBOutlet を使用してコードにバインドし、その高さを変更してテキストを具体的な垂直位置に表示することで、より柔軟に行うことができます。中央揃えと下揃えの例:

labelHeightConstraint.constant = centerAlignment ? 30 : 15
layoutIfNeeded()
于 2019-01-31T13:00:50.003 に答える
-1

これを試して !!あまりにも手動ですが、私にとっては完璧に機能します。

[labelName setText:@"This is just a demo"];

NSMutableString *yourString1= @"This is just a demo";


// breaking string
labelName.lineBreakMode=UILineBreakModeTailTruncation;
labelName.numberOfLines = 3;


CGSize maximumLabelSize1 = CGSizeMake(276,37); // Your Maximum text size

CGSize expectedLabelSize1 = [yourString1 sizeWithFont:labelName.font
                                    constrainedToSize:maximumLabelSize1
                                        lineBreakMode:labelName.lineBreakMode];

[labelName setText:yourString1];


CGRect newFrame1 = labelName.frame;
if (expectedLabelSize1.height>=10)
{
    newFrame1.size.height = expectedLabelSize1.height;
}

labelName.frame = newFrame1;
于 2012-11-11T11:01:27.530 に答える