ios - 文字 - uitextview 縦 中央




UILabel内でテキストを垂直方向に整列させる (20)

  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]
    

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

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

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

テキストを常にUILabel最上部に配置するにはどうすれば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


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


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

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

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

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

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

UILabel垂直方向の整列を設定する方法はありませんが、ラベルのフレームを変更することで同じ効果を得ることができます。 私は自分のラベルをオレンジ色にして、何が起きているのかを明確に見ることができます。

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

    [myLabel sizeToFit];

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

    myLabel.numberOfLines = 0;
    [myLabel sizeToFit];

より長いバージョン

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

- (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を使用する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 (デフォルト)は、他の2つの切り捨てモード(頭と中央)と同様に、 sizeToFit後で無視されます。 NSLineBreakByClippingも無視されます。 NSLineBreakByCharWrappingはいつものように動作します。 フレームの幅は、右端の文字に合わせてまだ狭められています。

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

autolayoutを使用するViewControllerのviewのサブビューとしてラベルがnibまたはstoryboardに含まれている場合、autolayoutはviewDidLoadが呼び出された後にサブビューのサイズと位置を決めるため、 sizeToFit呼び出しをviewDidLoad入れてもsizeToFitません。あなたのsizeToFit呼び出しの効果。 ただし、 viewDidLayoutSubviews内からsizeToFitを呼び出すとsizeToFitします。

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

これは、 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;

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

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

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


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

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

}

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

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

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


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

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]; あなたの各ラベルのテキストの割り当ての後。


新しいクラスを作成する

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

私は、複数行、最小フォントサイズを持つことができ、それが親ビューで水平方向と垂直方向の両方に集中できるラベルを持っていたいと思っていました。 私は自分のラベルをプログラム的に私の見解に加えました:

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

誰かを助けることを願って!


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

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

自動レイアウトは、この問題をかなり簡単にします。 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


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

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つのソリューションのどちらも単独では機能しませんでしたが、ちょっとした工夫をしても、私は上記のソリューションをまとめて合成することができました。


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

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

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

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


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

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

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


適応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

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


Interface Builderで

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

あなたのコードで

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

コードスニペット:

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






text-alignment