ios 文字 UILabel内でテキストを垂直方向に整列させる




uitextview 縦 中央 (24)

マッスルではない、大騒ぎしない

@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

いいえ、マス、いいえ目的-c、大騒ぎではないがスイフト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)
    }

}

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

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


TTTAttributedLabelを使用すると、垂直方向の配置がサポートされます。

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

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

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


私はこの質問の答えがちょっと古くなったので、そこに自動レイアウトファンを追加しました。

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


UILabel代わりに、垂直配置オプションを持つUITextFieldを使用することができます:

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

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

しかし、helveticaを使って作業すると、テキストが垂直方向にセンタリングされます。


迅速に、

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


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

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


私はこれが古い投稿であることは分かっていますが、テキストを縦に並べることは(少なくとも私にとっては)大きな問題です。私は自分自身を見つけることができなかったので、この解決方法を共有するべきだと思いました。

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:呼び出され、テキストを適切に揃えるためのオフセットサイズを計算することができます。

私はこれを信用できません、元の考えはhereから来ましhere。しかし、このソリューションはiOS7では動作しません。SOの周りを数時間追跡した後、私はこれを見つけました:iOS 7の垂直方向の位置合わせ。そこにキーラインがありますcontentheight = [tv sizeThatFits:CGSizeMake(tv.frame.size.width, FLT_MAX)].height; 。何らかの理由でiOS 7でcontentSizeの高さを取得しても機能しませんが、それを修正します。2つのソリューションのどちらも単独では機能しませんでしたが、ちょっとした工夫をしても、私は上記のソリューションをまとめて合成することができました。


UILabelをサブクラス化し、描画矩形を以下のように制約します。

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

    [super drawTextInRect:rect];
}

私は、改行パディングを含む解決策を試してみて、場合によっては正しく動作しませんでした。 私の経験では、上記のようにnumberOfLinesを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];
}

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

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

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


拡張ソリューションの参照:

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 alignTop];呼び出し[yourLabel alignTop]; または[yourLabel alignBottom]; あなたの各ラベルのテキストの割り当ての後。


他の人に助けてもらうために、同じ問題がありましたが、 UILabel使用からUILabel使用に切り替えるだけで問題を解決できUITextView 。 機能性が少し違っているので、これは誰にとっても分かりません。

UITextViewを使用するように切り替えると、スクロールビューのすべてのプロパティとユーザーインタラクションを有効にすることができます。これにより、ラベルのように機能するようになります。


上記の答えと同様ですが、コードに叩かれるのは簡単ではないか、簡単なので、少しきれいにしました。 この拡張モジュールを自分自身の.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];

私はこれと長い間闘ってきましたが、私は解決策を分かち合いたいと思っていました。

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

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

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

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

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

時には十分に良いことがあるので。


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

ここで述べるようhere


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

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

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

  1. 新しいテキストを設定する:

    myLabel.text = @"Some Text"
    
  2. maximum numbermaximum numberを0(自動)に設定する:

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

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

    [myLabel sizeToFit]
    

ラベルのフレームは、テキストに収まるだけの高さと幅です。 左上は変更しないでください。 私はこれを、左上揃えのテキストでのみテストしました。 他のアライメントでは、後でフレームを修正する必要があります。

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


Interface Builderで

  • UILabelを可能な最大サイズのテキストに設定する
  • 属性インスペクタでLinesを '0'に設定する

あなたのコードで

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

コードスニペット:

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

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

// adjust the height of a multi-line label to make it align vertical with top
+ (void) alignLabelWithTop:(UILabel *)label {
  CGSize maxSize = CGSizeMake(label.frame.size.width, 999);
  label.adjustsFontSizeToFitWidth = NO;

  // get actual height
  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;
[Utils alignLabelWithTop:lblHello];

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


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

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

このソリューションは誰にとってもうまくいかないでしょう。特に、あなたが表示している行数を超えても文字列の最後に "..."を表示したい場合は、次のいずれかを使用する必要があります。コードの長さが長くなりますが、多くの場合、必要なものが得られます。


適応UI(iOS8以降)の場合、UILabelの垂直方向の整列は、プロパティnoOfLines = 0`を変更することによってStoryBoardから設定されます。

制約

  1. UILabel LefMargin、RightMargin、およびTop Margin Constraintsの調整。

  2. Content Compression Resistance Priority For Vertical = Horizo​​ntalのように、 Content Compression Resistance Priority For Vertical = 1000に変更します。

編集:

noOfLines=0

所望の結果を達成するのに十分な以下の制約がある。





text-alignment