545

UITextViewコンテンツに合わせてa のサイズを調整する良い方法はありますか? たとえば、UITextView1 行のテキストを含む があるとします。

"Hello world"

次に、別のテキスト行を追加します。

"Goodbye world"

rectそれに応じて親ビューを調整できるように、テキストビューのすべての行を保持するを取得するための Cocoa Touch の良い方法はありますか?

別の例として、Calendar アプリケーションのイベントのメモのフィールドを見てください。セル (およびセルUITextViewに含まれる) が拡張されて、メモの文字列内のすべてのテキスト行が保持されることに注意してください。

4

41 に答える 41

638

これは、iOS 6.1 と iOS 7 の両方で機能します。

- (void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    textView.frame = newFrame;
}

または Swift (iOS 11 の Swift 4.1 で動作)

let fixedWidth = textView.frame.size.width
let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
textView.frame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)

iOS 6.1 のサポートが必要な場合は、次のことも行う必要があります。

textview.scrollEnabled = NO;
于 2013-09-21T10:26:20.690 に答える
579

これは iOS 7 以降では機能しなくなりました

UITextView実際には、コンテンツの正しい高さにサイズ変更する非常に簡単な方法があります。を使用して実行できますUITextView contentSize

CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

注意すべきことの 1 つは、 が でビューに追加されたcontentSizeのみ、正しいものを使用できることです。それ以前は等しいUITextViewaddSubviewframe.size

自動レイアウトがオンの場合、これは機能しません。自動レイアウトでは、メソッドを使用して高さの制約sizeThatFitsの値を更新するのが一般的な方法です。constant

CGSize sizeThatShouldFitTheContent = [_textView sizeThatFits:_textView.frame.size];
heightConstraint.constant = sizeThatShouldFitTheContent.height;

heightConstraintストーリーボードで作成された高さの制約にプロパティをリンクすることにより、通常 IBOutlet を介して設定するレイアウトの制約です。


この驚くべき答え、2014年に追加するのは、次の場合です。

[self.textView sizeToFit];

iPhone6+のみで動作に違いがあります。

ここに画像の説明を入力

6+ のみ (5s または 6 ではない) では、UITextView に「もう 1 行の空白行」が追加されます。「RL ソリューション」はこれを完全に修正します。

CGRect _f = self.mainPostText.frame;
_f.size.height = self.mainPostText.contentSize.height;
self.mainPostText.frame = _f;

6+ での「余分な行」の問題を修正します。

于 2010-03-21T14:26:31.360 に答える
93

コードとストーリーボードの両方を使用した非常に簡単なソリューション。

コード別

textView.scrollEnabled = false

絵コンテ別

スクロール有効のチェックを外す

ここに画像の説明を入力

これ以外に何もする必要はありません。

于 2016-07-17T07:06:09.627 に答える
19

誰かがこの時点まで読む勇気がある(または十分に絶望している)場合に備えて、ページの下部に適切な解決策を投稿します.

そのすべてのテキストを読みたくない人のための gitHub リポジトリは次のとおりです

これは iOs7 で動作し (iOs8 でも動作すると思います)、自動レイアウトで動作します。マジックナンバーは必要なく、レイアウトを無効にしたり、そのようなものを使用したりできます。短くエレガントなソリューション。

私は、すべての制約関連のコードはupdateConstraintsメソッドに行くべきだと思います。それでは、自分で作ってみましょうResizableTextView

viewDidLoadここで最初に遭遇する問題は、メソッドの前に実際のコンテンツ サイズがわからないことです。フォント サイズや改行などに基づいて、長くてバグのある道をたどって計算することはできますが、堅牢なソリューションが必要なので、次のようにします。

CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

これで、前か後かに関係なく、実際の contentSize がわかりviewDidLoadます。次に、textView に高さの制約を追加します (ストーリーボードまたはコードを介して、方法に関係なく)。その値を次のように調整しますcontentSize.height

[self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
    if (constraint.firstAttribute == NSLayoutAttributeHeight) {
        constraint.constant = contentSize.height;
        *stop = YES;
    }
}];

最後に行うことは、スーパークラスを に伝えることupdateConstraintsです。

[super updateConstraints];

クラスは次のようになります。

ResizableTextView.m

- (void) updateConstraints {
    CGSize contentSize = [self sizeThatFits:CGSizeMake(self.frame.size.width, FLT_MAX)];

    [self.constraints enumerateObjectsUsingBlock:^(NSLayoutConstraint *constraint, NSUInteger idx, BOOL *stop) {
        if (constraint.firstAttribute == NSLayoutAttributeHeight) {
            constraint.constant = contentSize.height;
            *stop = YES;
        }
    }];

    [super updateConstraints];
}

きれいできれいですね。そして、コントローラでそのコードを扱う必要はありません!

ちょっと待って! Y NO ANIMATION!

変更を簡単にアニメートして、textViewストレッチをスムーズにすることができます。次に例を示します。

    [self.view layoutIfNeeded];
    // do your own text change here.
    self.infoTextView.text = [NSString stringWithFormat:@"%@, %@", self.infoTextView.text, self.infoTextView.text];
    [self.infoTextView setNeedsUpdateConstraints];
    [self.infoTextView updateConstraintsIfNeeded];
    [UIView animateWithDuration:1 delay:0 options:UIViewAnimationOptionLayoutSubviews animations:^{
        [self.view layoutIfNeeded];
    } completion:nil];
于 2014-07-25T07:32:55.927 に答える
14

試しました[textView sizeThatFits:textView.bounds]か?

編集: sizeThatFits はサイズを返しますが、実際にはコンポーネントのサイズを変更しません。それがあなたの望むものなのか、それとも[textView sizeToFit]あなたが探していたもの以上のものなのかはわかりません。いずれにしても、ご希望の内容にピッタリ合うかはわかりませんが、まずはお試しください。

于 2008-09-08T20:36:56.947 に答える
10

NSString別の方法は、メソッドを使用して特定の文字列が占めるサイズを見つけることです。

-(CGSize)sizeWithFont:(UIFont *)font constrainedToSize:(CGSize)size

これは、指定されたフォントで指定された文字列に適合する四角形のサイズを返します。目的の幅と最大高さのサイズを渡すと、テキストに合わせて返された高さを確認できます。改行モードを指定できるバージョンもあります。

その後、返されたサイズを使用して、ビューのサイズを変更してフィットさせることができます。

于 2008-09-20T06:19:17.460 に答える
9

制約によってそれを行うことができます。

  1. UITextView の高さの制約を設定します。 ここに画像の説明を入力

2.その高さの制約に対して IBOutlet を作成します。

 @property (weak, nonatomic) IBOutlet NSLayoutConstraint *txtheightconstraints;

3.テキストビューにデリゲートを設定することを忘れないでください。

4.

-(void)textViewDidChange:(UITextView *)textView
{
    CGFloat fixedWidth = textView.frame.size.width;
    CGSize newSize = [textView sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
    CGRect newFrame = textView.frame;
    newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
    NSLog(@"this is updating height%@",NSStringFromCGSize(newFrame.size));
    [UIView animateWithDuration:0.2 animations:^{
                  _txtheightconstraints.constant=newFrame.size.height;
    }];

}

次に、このように制約を更新します:)

于 2016-03-04T07:16:20.687 に答える
8

便利なツールがない場合UITextView(たとえば、テーブル ビュー セルのサイズを変更している場合)、文字列を測定してサイズを計算する必要がありますUITextView。たとえば、テキスト ビューの希望の幅が分かっていて、対応する高さを知りたい場合は、次のようにします。

NSString * string = ...;
CGFloat textViewWidth = ...;
UIFont * font = ...;

CGSize size = CGSizeMake(textViewWidth - 8 - 8, 100000);
size.height = [string sizeWithFont:font constrainedToSize:size].height + 8 + 8;

ここでは、各 8 が 4 つのパディングされたエッジの 1 つを占めており、100000 は非常に大きな最大サイズとして機能します。

font.leading実際には、高さに余分を追加したい場合があります。これにより、テキストの下に空白行が追加されます。これは、テキスト ビューのすぐ下に視覚的に重いコントロールがある場合に見栄えが良くなる可能性があります。

于 2012-10-24T11:20:18.257 に答える
7

Mike McMaster's answer と組み合わせると、次のようなことができます。

[myTextView setDelegate: self];

...

- (void)textViewDidChange:(UITextView *)textView {
  if (myTextView == textView) {
     // it changed.  Do resizing here.
  }
}
于 2008-11-06T04:31:12.733 に答える
7

テキスト フィールド内のテキストに応じてテキスト フィールドの高さを変更し、テキスト フィールドの高さに基づいてその下にラベルを配置する方法を見つけました。これがコードです。

UITextView *_textView = [[UITextView alloc] initWithFrame:CGRectMake(10, 10, 300, 10)];
NSString *str = @"This is a test text view to check the auto increment of height of a text view. This is only a test. The real data is something different.";
_textView.text = str;

[self.view addSubview:_textView];
CGRect frame = _textView.frame;
frame.size.height = _textView.contentSize.height;
_textView.frame = frame;

UILabel *lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, 5 + frame.origin.y + frame.size.height, 300, 20)];
lbl.text = @"Hello!";
[self.view addSubview:lbl];
于 2011-03-14T10:13:32.440 に答える
4

これは@jhibberdの迅速なバージョンです

    let cell:MsgTableViewCell! = self.tableView.dequeueReusableCellWithIdentifier("MsgTableViewCell", forIndexPath: indexPath) as? MsgTableViewCell
    cell.msgText.text = self.items[indexPath.row]
    var fixedWidth:CGFloat = cell.msgText.frame.size.width
    var size:CGSize = CGSize(width: fixedWidth,height: CGFloat.max)
    var newSize:CGSize = cell.msgText.sizeThatFits(size)
    var newFrame:CGRect = cell.msgText.frame;
    newFrame.size = CGSizeMake(CGFloat(fmaxf(Float(newSize.width), Float(fixedWidth))), newSize.height);
    cell.msgText.frame = newFrame
    cell.msgText.frame.size = newSize        
    return cell
于 2015-03-07T16:02:09.333 に答える
4

UITextViewこれは、特定の領域に合わせてテキストを作成する必要がある場合にうまく機能しました。

// テキストはすでにサブビューに追加されている必要があります。そうしないと、contentviewsize が正しくなくなります。

- (void) reduceFontToFit: (UITextView *)tv {
    UIFont *font = tv.font;
    double pointSize = font.pointSize;

    while (tv.contentSize.height > tv.frame.size.height && pointSize > 7.0) {
        ポイントサイズ -= 1.0;
        UIFont *newFont = [UIFont fontWithName:font.fontName size:pointSize];
        tv.font = newFont;
    }
    if (pointSize != font.pointSize)
        NSLog(@"フォントを %.1f から %.1f にダウン", pointSize, tv.font.pointSize);
}
于 2012-10-08T17:59:10.417 に答える
3

これは、ユーザーがオンザフライでテキストを書き込んだ後に TextView に合わせたい場合に備えて、 Swift 5でうまく機能します。

UITextViewDelegateを次のように実装するだけです。

func textViewDidChange(_ textView: UITextView) {
    let newSize = textView.sizeThatFits(CGSize(width: CGFloat.greatestFiniteMagnitude, height: CGFloat.greatestFiniteMagnitude))
    textView.frame.size = CGSize(width: newSize.width, height: newSize.height)
}
于 2019-12-09T13:45:52.267 に答える
3

iOS 7.0 の場合、 を に設定する代わりにframe.size.height(contentSize.height現在は何もしません) を使用します[textView sizeToFit]

この質問を参照してください。

于 2013-09-20T02:39:00.403 に答える
2

1"Ronnie Liew"+4"user63934" (私のテキストは Web サービスから届きます): 1000 に注意してください (「私の場合」にそれほど大きなものはありません)

UIFont *fontNormal = [UIFont fontWithName:FONTNAME size:FONTSIZE];

NSString *dealDescription = [client objectForKey:@"description"];

//4
CGSize textSize = [dealDescription sizeWithFont:fontNormal constrainedToSize:CGSizeMake(containerUIView.frame.size.width, 1000)];

CGRect dealDescRect = CGRectMake(10, 300, containerUIView.frame.size.width, textSize.height);

UITextView *dealDesc = [[[UITextView alloc] initWithFrame:dealDescRect] autorelease];

dealDesc.text = dealDescription;
//add the subview to the container
[containerUIView addSubview:dealDesc];

//1) after adding the view
CGRect frame = dealDesc.frame;
frame.size.height = dealDesc.contentSize.height;
dealDesc.frame = frame;

そしてそれは... 乾杯

于 2012-07-30T01:56:34.430 に答える
1

テキストのサイズに応じて UITextView の高さを変更することがわかった最良の方法。

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX)];

または使用できます

CGSize textViewSize = [YOURTEXTVIEW.text sizeWithFont:[UIFont fontWithName:@"SAMPLE_FONT" size:14.0]
                       constrainedToSize:CGSizeMake(YOURTEXTVIEW.frame.size.width, FLT_MAX) lineBreakMode:NSLineBreakByTruncatingTail];
于 2013-09-06T06:27:03.373 に答える
1

機能する唯一のコードは、上記の jhibberd の回答のように 'SizeToFit' を使用するコードですが、ViewDidAppear で呼び出すか、UITextView テキスト変更イベントに配線しない限り、実際には取得されませ

于 2015-04-08T08:25:57.160 に答える
1

お役に立てれば:

- (void)textViewDidChange:(UITextView *)textView {
  CGSize textSize = textview.contentSize;
  if (textSize != textView.frame.size)
      textView.frame.size = textSize;
}
于 2010-03-17T17:31:32.510 に答える
1

Nikita Take's answer に基づいて、自動レイアウトを使用して iOS 8 で動作する Swift の次のソリューションにたどり着きました。

    descriptionTxt.scrollEnabled = false
    descriptionTxt.text = yourText

    var contentSize = descriptionTxt.sizeThatFits(CGSizeMake(descriptionTxt.frame.size.width, CGFloat.max))
    for c in descriptionTxt.constraints() {
        if c.isKindOfClass(NSLayoutConstraint) {
            var constraint = c as! NSLayoutConstraint
            if constraint.firstAttribute == NSLayoutAttribute.Height {
                constraint.constant = contentSize.height
                break
            }
        }
    }
于 2015-05-13T12:46:46.857 に答える
0

この方法はios7で機能するようです

 // Code from apple developer forum - @Steve Krulewitz, @Mark Marszal, @Eric Silverberg
- (CGFloat)measureHeight
{
    if ([self respondsToSelector:@selector(snapshotViewAfterScreenUpdates:)])
    {
    CGRect frame = internalTextView.bounds;
    CGSize fudgeFactor;
    // The padding added around the text on iOS6 and iOS7 is different.
    fudgeFactor = CGSizeMake(10.0, 16.0);

    frame.size.height -= fudgeFactor.height;
    frame.size.width -= fudgeFactor.width;

    NSMutableAttributedString* textToMeasure;
    if(internalTextView.attributedText && internalTextView.attributedText.length > 0){
        textToMeasure = [[NSMutableAttributedString alloc] initWithAttributedString:internalTextView.attributedText];
    }
    else{
        textToMeasure = [[NSMutableAttributedString alloc] initWithString:internalTextView.text];
        [textToMeasure addAttribute:NSFontAttributeName value:internalTextView.font range:NSMakeRange(0, textToMeasure.length)];
    }

    if ([textToMeasure.string hasSuffix:@"\n"])
    {
        [textToMeasure appendAttributedString:[[NSAttributedString alloc] initWithString:@"-" attributes:@{NSFontAttributeName: internalTextView.font}]];
    }

    // NSAttributedString class method: boundingRectWithSize:options:context is
    // available only on ios7.0 sdk.
    CGRect size = [textToMeasure boundingRectWithSize:CGSizeMake(CGRectGetWidth(frame), MAXFLOAT)
                                              options:NSStringDrawingUsesLineFragmentOrigin
                                              context:nil];

    return CGRectGetHeight(size) + fudgeFactor.height;
}
else
{
    return self.internalTextView.contentSize.height;
}
}
于 2013-09-29T22:56:33.403 に答える
0

The easiest way to ask a UITextView is just calling -sizeToFitit should work also with scrollingEnabled = YES, after that check for the height and add a height constraint on the text view with the same value.
Pay attention that UITexView contains insets, this means that you can't ask the string object how much space it want to use, because this is just the bounding rect of the text.
All the person that are experiencing wrong size using -sizeToFit it's probably due to the fact that the text view has not been layout yet to the interface size.
This always happen when you use size classes and a UITableView, the first time cells are created in the - tableView:cellForRowAtIndexPath: the comes out with the size of the any-any configuration, if you compute you value just now the text view will have a different width than the expected and this will screw all sizes.
To overcome this issue I've found useful to override the -layoutSubviews method of the cell to recalculate textview height.

于 2015-10-22T07:41:30.153 に答える