web-dev-qa-db-ja.com

UILabel内でテキストを上に垂直に配置

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

テキストを常にUILabelの一番上になるように垂直方向に揃える方法

image representing a UILabel with vertically-centered text

2057
Stefan

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

これを行うための迅速で簡単な方法は次のとおりです。

    [myLabel sizeToFit];

sizeToFit to squeeze a label


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

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

Longer label text with sizeToFit


長いバージョン

何が起こっているのかわかるように、ラベルをコードにします。このほとんどをInterface Builderでも設定できます。私のセットアップは、私がマージン(20ポイント)を表示するためにPhotoshopで作った背景画像を持つView Based Appです。ラベルは魅力的なオレンジ色なので、寸法を見ればわかります。

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

enter image description here

ラベルはまだ左上隅が固定されています。元のラベルの幅を変数に保存して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;

label alignment


sizeToFitは、初期ラベルの最小幅を考慮します。幅が100幅のラベルから始めて、その上にsizeToFitを呼び出すと、幅が100(またはそれより少し小さい)幅の(おそらく非常に高い)ラベルが返されます。サイズを変更する前に、ラベルを希望の最小幅に設定することをお勧めします。

Correct label alignment by resizing the frame width

注意する他のいくつかのこと:

lineBreakModeが尊重されるかどうかは、設定​​方法によって異なります。他の2つの切り捨てモード(headとmiddle)と同様に、NSLineBreakByTruncatingTail(デフォルト)はsizeToFitの後で無視されます。 NSLineBreakByClippingも無視されます。 NSLineBreakByCharWrappingは通常どおり動作します。枠の幅は、右端の文字に合うように狭くなっています。


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

自動レイアウトを使用するViewControllerのviewのサブビューとしてラベルがペン先またはストーリーボードに含まれている場合、sizeToFit呼び出しをviewDidLoadに設定しても機能しません。 viewDidLoadが呼び出された後にサブビューを配置し、すぐにsizeToFit呼び出しの効果を元に戻します。ただし、sizeToFitwill内からviewDidLayoutSubviewsを呼び出すことは機能します。


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

これはNSStringメソッドsizeWithFont:constrainedToSize:lineBreakMode:を使って文字列に合わせるのに必要なフレームの高さを計算してから、Originとwidthを設定します。

挿入するテキストを使用してラベルの枠のサイズを変更します。そうすれば、何行にでも対応できます。

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;
2617
nevan king
  1. 新しいテキストを設定します。

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

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

    myLabel.frame = CGRectMake(20,20,200,800)
    
  4. 内容がぴったり収まるようにフレームサイズを小さくするにはsizeToFitを呼び出します。

    [myLabel sizeToFit]
    

ラベルフレームはテキストのサイズに合うように高さと幅が調整されています。左上は変更されません。私はこれを左上揃えのテキストでのみテストしました。他の配置では、後でフレームを修正する必要があるかもしれません。

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

322
Jakob Egger

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

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も@" \[email protected]%"の代わりに"\[email protected]%"で更新する必要があります(サイクルの初期化は "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];を呼び出します。

155

念のために言っておきますが、私は同じ問題を抱えていましたが、単にUILabelの使用からUITextViewの使用に切り替えることで問題を解決することができました。機能が少し違うので、これが皆のためではないことを私は感謝します。

UITextViewを使用するように切り替えた場合は、Scroll ViewプロパティとUser Interaction Enabled ...をすべて無効にすることができます。これにより、ラベルのように動作するようになります。

enter image description here

131
jowie

大騒ぎも大騒ぎも

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

}
89
jasongregori

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

これを達成するためのさらに速く(そしてより汚い)方法は、UILabelの改行モードを "Clip"に設定し、固定量の改行を追加することです。

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

この解決法はすべての人にとってうまくいくわけではありません。特に、表示する行数を超えている場合でも、文字列の末尾に "..."を表示する場合は、長いコード - しかし多くの場合、これはあなたが必要なものを手に入れるでしょう。

67

UILabelの代わりに、垂直方向の整列オプションを持つUITextFieldを使用することができます。

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

私は長い間これと闘ってきました、そして私は私の解決策を共有したいと思いました。

これはあなたに0.5スケールまでテキストを自動的に縮小し、テキストを垂直方向に中央寄せするUILabelを与えるでしょう。これらのオプションはStoryboard/IBでも利用できます。

[labelObject setMinimumScaleFactor:0.5];
[labelObject setBaselineAdjustment:UIBaselineAdjustmentAlignCenters];
48
David Greco

新しいクラスを作る 

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
42

enter image description here

Interface Builderで

  • UILabelを可能な限り大きいテキストのサイズに設定します
  • 属性インスペクタでLinesを '0'に設定します

あなたのコードで

  • ラベルのテキストを設定します
  • ラベルにsizeToFitを呼び出します

コードスニペット:

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

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

議論したように ここ

33
Martin Wickman

アダプティブUI(iOS 8以降)の場合は、プロパティを変更することでStoryBoardからUILabelの垂直方向の配置を設定する必要があります noOfLinesname __ = 0`および 

制約

  1. UILabelのLefMargin、RightMargin、およびTop Marginの制約を調整します。

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

Constraints of UILabel

編集済み:

noOfLines=0

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

enter image description here

32

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

 //複数行のラベルの高さを調整して、垂直方向にtop 
 +(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 = @ "ハローワールド!ハローワールド!ハローワールド!ハローワールド!ハローワールド!ハローワールド!ハローワールド!」; 
 lblHello.numberOfLines = 5; [。 [Util.alignLabelWithTop:lblHello]; 

私は記事としてそれを私のブログにも書いた: http://fstoke.me/blog/?p=2819

27
firestoke

紹介されているページのコードと同様にコードを読むのにしばらく時間がかかりました、そして、彼ら全員がラベルのフレームサイズを修正しようとしているので、デフォルトの中央の垂直方向の整列は現れないでしょう。

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

ここで、私はそれを解決するために代わりの方法を使いました、単にラベルの終わりまで改行を詰めることによって(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 "];
}
26
Walty Yeung

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

TTTAttributedLabel を使うことができます。

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

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

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

自動レイアウトはこの問題をかなり簡単にします。ラベルを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の上部に水平方向に配置されます。

14
petehare

私は、複数行、最小フォントサイズ、そして親ビューの水平方向と垂直方向の両方の中央に配置できるラベルを作成したいと思いました。プログラムで自分のラベルを自分のビューに追加しました。

- (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
Johnus

私は上記の多くの方法を使ってきました、そして私が使った簡単なアプローチを加えたいだけです:

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

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

十分に良い場合があるので 十分に良い

14
Code Roadie

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

13
jjxtra

ラベル内のテキストが縦方向に中央揃えされていないため、これを読む人のために、フォントの種類によってはデザインが等しくないことに注意してください。たとえば、サイズが16のzapfinoのラベルを作成すると、テキストは垂直方向の中央に配置されません。

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

11
Nir Pengas

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

10
phatmann

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

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

    [super drawTextInRect:rect];
}

改行パディングを含む解決策を試してみたところ、場合によっては正しくない動作が発生しました。私の経験では、numberOfLinesで混乱させるよりも上のように描画四角形を拘束する方が簡単です。

P.Sあなたはこのように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
jrc

スウィフトでは、

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

7
Dara Tith

複雑な作業をしていない限り、UITextViewの代わりにUILabelsを使用できます。

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

テキストを完全に表示したい場合は、ユーザーのsizeToFitメソッドとsizeThatFits:メソッドだけを使用してください。

7
thesummersign

textRect(forBounds:limitedToNumberOfLines:)を使用してください。

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

これは古い解決策です、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
6
Sulthan

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

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

6
atul awasthi

独自のカスタムビューを作成することが選択肢である場合は、次のようにします。

- (void)drawRect:(CGRect)rect
{
    CGRect bounds = self.bounds;
    [self.textColor set];
    [self.text drawInRect:bounds
                 withFont:self.font
            lineBreakMode:UILineBreakModeTailTruncation
                alignment:self.textAlignment];
}
6
jcjimenez

これは古い投稿だと思いますが、テキストを垂直方向に整列させることは(少なくとも私にとっては)大きな問題です。自分で見つけることができなかったので、この解決策を共有するべきだと考えました。 

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

- (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:が呼び出され、オフセットサイズを計算できますテキストを適切に配置します。 

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

6
barndog

私のアプリでしたことは、UILabelのlineプロパティを0に設定することと、UILabelの下部制約を作成して、下の画像に示すように> = 0に設定されていることを確認することでした。 enter image description here

5
Jack
yourLabel.baselineAdjustment = UIBaselineAdjustmentAlignCenters;
5
mbo42

Swift 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 Extensionを使う:

空の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)
5
A.G

私はその特定の問題にも取り組んでいたので、 DS nevan king という考えを取り、基本的にそれらを垂直方向の整列プロパティを実装するサブクラスにまとめました。配置を1回以上変更できます。これはUIControlContentVerticalAlignment型を借用し、UIControlContentVerticalAlignmentFillもサポートします。

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

そこにあります: GitHub上のQALabel

5
vbwx

私は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)); 
        }
    }
}
5
sean woodward

Swift 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
    }
}
4
seggy

この問題を解決するには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番目の方法は、表示されるテキストのサイズに応じて最終的にフレームを設定します。

4
SunnyChattha

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

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

isHeightToChangeデフォルトではtrueに設定されているため、ラベルの高さは自動的にテキストコンテンツと同じになります。 isHeightToChange falseの場合、ラベルの高さを下げずにテキストを上に揃えます。

#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
3
Ramesh Muthe

この問題を解決しようとしているカスタムテーブルセルをお持ちの方は、これをカスタムテーブルセルクラスに追加してください。

Swift 2.2:

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

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

3
Elliott Davies

(2018年3月7日現在)

スイフト4

let maxFrameHeight = 75

myLabel = UILabel()
myLabel.frame = CGRect(x: 9, y: 9, width: 126, height: maxFrameHeight)
myLabel.text = "my labels text displayed"
myLabel.numberOfLines = 0

myLabel.sizeToFit()
let newFrameHeight = myLabel.frame.size.height
let safeNewHeight = min(newFrameHeight, maxFrameHeight)

myLabel.frame = CGRect(x: 9, y: 9, width: 126, height: safeNewHeight)

これは望ましい結果を得るでしょう、そしてそれはUILabelの新しい高さがあなたがこのラベルのために望むある最大の高さを通過しないことを確かにするでしょう。

3
BennyTheNerd

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

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

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

3
KarenAnne

投稿された他のすべてのソリューションを基にして、alignmentプロパティを設定するときに垂直方向のアライメントを処理する簡単な小さな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];
}
2
cohen72

この問題に対する簡単な解決策 

ラベルの下にUIStackViewを配置します。 

次に、AutoLayoutを使用してラベルの垂直方向の間隔を0に設定し、上部をラベルの下部にあるものに固定します。ラベルは大きくならず、stackViewは大きくなります。私がこれについて好きなのは、スタックビューがレンダリングされていないということです。それで、それは本当に時間レンダリングを無駄にしていません。オートレイアウトの計算をしても。

あなたはおそらくContentHuggingとResistanceで遊ぶ必要があるでしょうが、それも同様に簡単です。 

時々私はこの問題をグーグルしてここに戻ってきます。今回は私が一番簡単だと思う考えを持っていました、そしてそれが悪いパフォーマンス賢明だとは思わない。 私はAutoLayoutを使っているだけで、フレームの計算に迷惑をかけたくないと言う必要があります。それはただ…ヤックです。

1
Nuno Gonçalves

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

labelHeightConstraint.constant = centerAlignment ? 30 : 15
layoutIfNeeded()
0
Ruben Marin

これがSwift 4.0の解決策です。

func viewDidLoad() {

    super.viewDidLoad()

    // 20 point top and left margin. Sized to leave 20 pt at right.
    let labelFrame = CGRect(x: 20, y: 20, width: 280, height: 150)
    let myLabel = UILabel(frame: labelFrame)
    myLabel.backgroundColor = UIColor.orange

    let labelText = "I am the very model of a modern Major-General, 
    I've information vegetable, animal, and mineral"
    myLabel.text = labelText

    // Tell the label to use an unlimited number of lines
    myLabel.numberOfLines = 0
    myLabel.sizeToFit()

    view.addSubview(myLabel) // add label
}
0
Ashish