UILabel内でテキストを垂直方向に上揃えします


2175

私は持っています UILabel 2行のテキストのためのスペースで。テキストが短すぎる場合、このテキストはラベルの垂直方向の中央に表示されることがあります。

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

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

回答:


2702

垂直方向の配置を設定する方法はありません UILabelんが、ラベルのフレームを変更することで同じ効果を得ることができます。ラベルをオレンジにして、何が起こっているのかはっきりとわかるようにしています。

これをすばやく簡単に行う方法は次のとおりです。

    [myLabel sizeToFit];

ラベルを絞るsizeToFit


複数の行を作成する長いテキストのラベルがある場合は、に設定numberOfLinesします0(ここでのゼロは、無制限の行数を意味します)。

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

sizeToFitを使用した長いラベルテキスト


長いバージョン

何が起こっているかを確認できるように、コードでラベルを作成します。このほとんどは、Interface Builderでも設定できます。私の設定は、余白(20ポイント)を表示するためにPhotoshopで作成した背景画像を含むビューベースのアプリです。ラベルは魅力的なオレンジ色なので、寸法で何が起こっているかを確認できます。

- (void)viewDidLoad
{
    [super viewDidLoad];

    // 20 point top and left margin. Sized to leave 20 pt at right.
    CGRect labelFrame = CGRectMake(20, 20, 280, 150);
    UILabel *myLabel = [[UILabel alloc] initWithFrame:labelFrame];
    [myLabel setBackgroundColor:[UIColor orangeColor]];

    NSString *labelText = @"I am the very model of a modern Major-General, I've information vegetable, animal, and mineral";
    [myLabel setText:labelText];

    // Tell the label to use an unlimited number of lines
    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    [self.view addSubview:myLabel];
}

sizeToFit中央揃えまたは右揃えのテキストでは、使用に関するいくつかの制限が関係します。ここで何が起こるかです:

    // myLabel.textAlignment = NSTextAlignmentRight;
    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

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

ラベルのサイズは、左上隅が固定されたままです。元のラベルの幅を変数に保存してに設定するsizeToFitか、固定幅を指定してこれらの問題に対抗できます。

    myLabel.textAlignment = NSTextAlignmentCenter;

    [myLabel setNumberOfLines:0];
    [myLabel sizeToFit];

    CGRect myFrame = myLabel.frame;
    // Resize the frame's width to 280 (320 - margins)
    // width could also be myOriginalLabelFrame.size.width
    myFrame = CGRectMake(myFrame.origin.x, myFrame.origin.y, 280, myFrame.size.height);
    myLabel.frame = myFrame;

ラベルの配置


sizeToFit最初のラベルの最小幅が尊重されることに注意してください。幅100のラベルから始めてsizeToFitそれを呼び出すと、幅が100(または少し少ない)の(おそらく非常に高い)ラベルが返されます。サイズを変更する前に、ラベルを必要な最小幅に設定することをお勧めします。

フレーム幅のサイズを変更してラベルの配置を修正する

その他の注意事項:

lineBreakMode尊重されるかどうかは、それがどのように設定されているかによって異なります。NSLineBreakByTruncatingTail(デフォルト)はsizeToFit、他の2つの切り捨てモード(ヘッドとミドル)と同様に、後に無視されます。NSLineBreakByClippingも無視されます。NSLineBreakByCharWrapping通常どおり機能します。フレーム幅は、右端の文字に合わせて狭められています。


Mark Ameryがコメントで自動レイアウトを使用してNIBとストーリーボードを修正しました:

viewautolayoutを使用するViewControllerのサブビューとしてラベルがnibまたはストーリーボードに含まれている場合、autolayoutが呼び出されてサブビューが配置sizeToFitviewDidLoadれるので、呼び出しは機能しませんviewDidLoadsizeToFitコール。ただし、sizeToFit内部からの呼び出しviewDidLayoutSubviews 機能します。


私の元の回答(後世/参照用):

これは、NSStringメソッドsizeWithFont:constrainedToSize:lineBreakMode:を使用して文字列を合わせるために必要なフレームの高さを計算し、次に原点と幅を設定します。

挿入するテキストを使用して、ラベルのフレームのサイズを変更します。これにより、任意の数の行に対応できます。

CGSize maximumSize = CGSizeMake(300, 9999);
NSString *dateString = @"The date today is January 1st, 1999";
UIFont *dateFont = [UIFont fontWithName:@"Helvetica" size:14];
CGSize dateStringSize = [dateString sizeWithFont:dateFont 
        constrainedToSize:maximumSize 
        lineBreakMode:self.dateLabel.lineBreakMode];

CGRect dateFrame = CGRectMake(10, 10, 300, dateStringSize.height);

self.dateLabel.frame = dateFrame;

10
autolayoutを削除する必要があります
hungbm06

4
問題を解決する簡単な方法は次のとおりです:stackoverflow.com/a/26632490/636559
AboulEinein

自動レイアウトとストーリーボードを使用する場合は、「ビルド時に削除」オプションをオンにして制約を追加すると効果的です
JK ABC

これをadjustsFontSizeToFitWidth使用する必要がある場合は、sizeToFitを使用してから、ラベルのフレームを0、0、theWidthYouWant、label.frame.size.height(sizeToFitによって決定される新しい高さ)に設定します。次に適用しますadjustsFontSizeToFitWidth
Albert Renshaw

3
この答えは不必要に複雑であり、「一言」を使用しています。垂直コンテンツのハグの優先順位を単に変更することについて、以下の提案を参照してください。コードは必要ありません...
beetree

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

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

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

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

    [myLabel sizeToFit]

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

また、私のラベルでは折り返しが有効になっています。


ちょっとベン、私は古いコードをもう一度見て、必要な正しい手順で私の答えを更新しました。
Jakob Egger

これは私にとってはうまくいきました。UILabelのサイズを設定し、IBでnumberOfLinesを0に変更してから、[myLabel sizeToFit]というテキストを設定しました。
ダン・エリス

Attrで行数を設定した後、私にとって完璧に動作します。インスペクター
d2burke 2012年

行数が1を超える場合は機能しません
Tom

2行のラベルが必要な場合は機能しませんが、テキストにはさらに行が必要です。
ホセマヌエルアバルカロドリゲス

159

拡張ソリューションを参照する:

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

iPhone UILabelsの末尾のキャリッジリターンは無視されるため、追加された改行ごとに追加のスペースが必要です:(

同様に、alignBottomも@" \n@%""\n@%"する必要があります(サイクルの初期化は「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];または[yourLabel alignBottom];を呼び出します。


@DSのVerticalAlign後の括弧の間に追加していることに気付きました@implementation UILabel。Objective-Cが初めてなので、この構文に出会ったことはありません。これは何と呼ばれていますか?
ジュリアン

驚くべきことに、カテゴリについては知りませんでした。これにより、Objective-c言語に対する理解がさらに深まります。より多くの言語を学ぶことは、優れたプログラマーになるために非常に重要です。
JeroenEijkhof、2011年

賛成票を与えました。しかし、iircは、欠点である行数がわからない場合は機能しません
Tjirp

3行のテキストを表示し、テキストを上に揃えます。したがって、行数を3に設定する必要がありますか。3に設定すると、テキストが少ない(1行に収まる)場合、「...」が表示されます。この「...」を回避する方法
Satyam

1
私はこのカテゴリの編集を投稿しました。うまくいけば、まもなく承認されるでしょう。メソッドsizeWithFont:constrainedToSize:lineBreakMode:とsizeWithFont:はどちらもiOS7では廃止されています。numberOfLinesが0より大きい場合にも、このカテゴリは、ラベルだけで動作します
timgcarlson

146

誰かの助けになった場合のために、私は同じ問題を抱えていましたが、使用から使用UILabelに切り替えるだけで問題を解決することができましたUITextView。機能が少し異なるので、これがすべての人に適しているわけではないことに感謝します。

を使用するように切り替える場合はUITextView、すべてのスクロールビューのプロパティとユーザー操作を有効にしてオフにすることができます。これにより、ラベルのように機能するように強制できます。

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


1
多くのUILabelがテキストビューに変換される場合、これがパフォーマンスにどのように影響するかはわかりません。
忍者

2
このスレッドの他のすべてのソリューションは、iOS 7では(何らかの理由で)機能しませんでした。しかし、単純にa UITextViewを使用すると、すぐに望ましい結果が得られました。
Clifton Labrum 14

1
これは回避策ですが、本物に見えるように調整する必要がありますが、これは私が見た中で最も簡単なnoneコードソリューションではありません。
Itai Spector

1
私はこのソリューションが好きです。確かに、パフォーマンスの問題などがある可能性があります。比較的単純なビューの単純なラベルの場合、これは私が必要とするものにぴったりでした(そして、パフォーマンスへの影響は
わかり

1
この方法の小さな欠点は、テキストに余分な組み込みパディングが導入されることです。簡単な修正は、負の制約を導入することです。
シララム2018

122

ムスも大騒ぎもない

@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)
    }

}

Swift 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)
    }

}

Swiftバージョンは副作用なしで私のために働いた!すごい仕事!
l.vasilev 2017年

2
おそらくここでの最良の答えは、すべてのシナリオで機能します。ラベルがUITableviewCellにある場合、sizeToFitは機能しません。よくできました。
rajat chauhan

79

上記の答えのように、しかしそれは完全に正しくなかったか、コードに平手打ちするのは簡単ではなかったので、私はそれを少し片付けました。この拡張子を独自の.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];

sizeWithFontは非推奨
tdios

68

これを達成するためのさらに迅速な(そしてダーティーな)方法は、UILabelの改行モードを「クリップ」に設定し、固定量の改行を追加することです。

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

この解決策は誰にとっても機能しません。特に、文字列の最後に「...」を表示したい場合は、表示している行数を超える場合は、次のいずれかを使用する必要があります。コードのより長いビット-しかし多くの場合、これはあなたが必要とするものを手に入れるでしょう。


3
改行モードを「clip」に設定すると、ラベルの自動サイズ設定が混乱するようです。UILineBreakModeWordWrap代わりに使用してください。
Niels van der Rest

さらにスペースを追加する "\ n \ n"
djdance

68

ストーリーボードを使用する最も簡単な方法:

StackViewにラベルを埋め込む、属性インスペクターでStackViewの次の2つの属性を設定します。

の1- AxisHorizontal

2 AlignmentからTop

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


1
より良い結果を得るには、このStackView> View> UILabelを実行します。これは、UILabelをStackView内に埋め込むだけで、StackViewのサイズが変更され、UILabelを最小サイズに合わせる
Daniel Beltrami

UILabel一部のUIViewサブクラスに配置し(UIView通常はプレーンで十分です)、そのラベルを下方向に拡張することをお勧めします。ありがとう!
Viktor Kucera 2018

1
驚くばかり!それはあなたがする必要があることにも言及する価値が明確な制約UILabelとStackViewはその仕事をやらせます。ありがとう!
Luiz Dias

ラベルを選択した状態で[エディター]-> [埋め込み]メニューコマンドを使用すると、Xcodeによってラベルの制約がクリアされ、StackViewの制約を設定できます。このアプローチは、「SwiftUI」レイアウトアプローチに最も近いものです。
ロケットガーデン

なぜこれが機能するのですか?
Novellizator

60

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

textField.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
textField.userInteractionEnabled = NO; // Don't allow interaction

7
警告:UITextFieldは単一行のテキストのみを許可します。
デビッドジェームズ14

2
@DavidJamesコメントを完了するには、UITextViewの方が適切です
CedricSoubrie

49

私はこれに長い間取り組んできましたが、自分の解決策を共有したいと思いました。

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

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];

提供されたすべての回答の中で完璧に機能しました。@David Grecoに感謝します。これらのプロパティとともに、adjustsFontSizeToFitWidthをYESに設定すると、テキストはラベルのフレームを変更せずにフレームに収まります。
Ashok

43

新しいクラスを作成する

LabelTopAlign

.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

本当の答えは+1。sizeToFitソリューションとは異なり、これは実際には短いテキストを長いテキストに動的に置き換えたり、その逆を行ったりしても、テキストを一番上にUILabel配置ます。
SnakE 2013

38

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

インターフェイスビルダーで

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

あなたのコードで

  • ラベルのテキストを設定する
  • sizeToFitあなたのレーベルに電話する

コードスニペット:

self.myLabel.text = @"Short Title";
[self.myLabel sizeToFit];

行を2に設定する必要がある場合を除いて、うまくいきました。UITableViewCell内にUILabelを設定し、0に設定するとオーバーラップしましたが、2に設定すると機能しました(セルに2行分のスペースがあります)
eselk

34

アダプティブUI(iOS8以降)の場合、UILabelの垂直方向の配置は、プロパティnoOfLines= 0`を変更してStoryBoardから設定します。

制約

  1. UILabel LefMargin、RightMargin、Top Margin Constraintsを調整します。

  2. Content Compression Resistance Priority For Vertical= 1000`を変更して、Vertical> Horizo​​ntalにします。

UILabelの制約

編集:

noOfLines=0

そして、次の制約は、望ましい結果を達成するのに十分です。

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


これは最高でした。垂直>水平が仕事をした理由を説明できますか?ありがとう。
ガブリエル

33

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

ここで議論したように


27

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

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

  //実際の高さを取得します
  CGSize actualSize = [label.text sizeWithFont:label.font constrainedToSize: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


27

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

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

ここでは、ラベルの最後まで改行を埋め込むだけで、別の方法で解決しました(実際にを継承したことに注意してください。ただし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 "];
}

22

アプリで行ったのは、UILabelのlineプロパティを0に設定し、UILabelの下部制約を作成して、下の画像に示すように> = 0に設定されていることを確認することです。 ここに画像の説明を入力してください


19

ここで提案を取り、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

19

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

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

//view's or viewController's init method
_label.verticalAlignment = TTTAttributedLabelVerticalAlignmentTop;

16

この質問の答えは少し古くなっているので、自動レイアウトファンのためにこれを追加します。

自動レイアウトにより、この問題はかなり簡単になります。ラベルをUIView *viewに追加すると仮定すると、次のコードでこれを実行できます。

UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero];
[label setText:@"Some text here"];
[label setTranslatesAutoresizingMaskIntoConstraints:NO];
[view addSubview:label];

[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"H:|[label]|" options:0 metrics:nil views:@{@"label": label}]];
[view addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:@"V:|[label]" options:0 metrics:nil views:@{@"label": label}]];

ラベルの高さは(を使用してintrinsicContentSize)自動的に計算され、ラベルはの上部に端から端まで水平に配置されviewます。


15

私は上記の方法の多くを使用しましたが、私が使用した迅速で汚いアプローチを追加したいだけです:

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

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

時々十分で良いので十分です。


ただし、iOSデバイスの画面サイズの高さにばらつきがある場合、uilabelの高さの変化(これは可能性があります)に対応するために、変数番号「\ n」が必要になります。したがって、この方法は特に有用な長期間ではありません。
Rambatino、2014

注:「いつでも完璧な解決策」ではなく「迅速かつ汚い」ものです。言ってるだけ'。
Code Roadie 2014

2
@CodeRoadieクイックアンドダーティがうまくやってくれました。実際の答えにはレイアウトの問題がいくつかありました。私はそれを「正しい方法」で行うことができましたが、時間を節約してくれてありがとう!
セラフィンHochart

@dGambitご注意ください:「クイックアンドダーティー
Code Roadie

1
ビューを動的に読み込むときに最近学んだUITextViewことはdlopen、テキスト入力をサポートするために呼び出すことができるということです。これにより、UIスレッドに大きな遅延が発生する可能性があるため、このアプローチははるかにパフォーマンスが高くなります。
yano 2015年

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

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


14

FXLabel(github上)は、に設定label.contentModeすることにより、デフォルトでこれを実行しますUIViewContentModeTop。このコンポーネントは私が作成したものではありませんが、私が頻繁に使用するコンポーネントであり、多くの機能を備えており、うまく機能しているようです。


11

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

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


多くのカスタムフォントは、垂直方向の中央揃えではありません。UILabelまたはUITextViewは常に垂直方向の中央揃えです。iOSプログラミングでの垂直方向の配置について考える必要はありません。
アミットシン2013年

11

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

class TopAlignedLabel: UILabel {
    override func drawText(in rect: CGRect) {
        let textRect = super.textRect(forBounds: bounds, limitedToNumberOfLines: numberOfLines)
        super.drawText(in: textRect)
    }
}

あなたは神です!
Diogo Antunes 2017年

1
この答えは、取得する必要の方法、それははるかに素敵なきれいな解決策であるように、よりupvotesを!
Michael Ochs、

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

10

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


8

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

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

テキストを完全に表示する場合はsizeToFit、ユーザーとsizeThatFits:メソッドのみ


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


の古い構文から構文を変更しただけです[myLabel sizeToFit]。ありがとうございました!
velkoon 2018年

7

これは古いソリューションです。iOSで自動レイアウトを使用します> = 6

私の解決策:

  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
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.