web-dev-qa-db-ja.com

UITextViewのサイズ変更

UITextViewUIViewを追加しました。追加されたテキストビューは編集できません。データを表示するだけです。テキストビューに表示されるデータは動的です。つまり、行数は固定されていません。異なる場合があります。したがって、行数が増えると、テキストビューのサイズも大きくする必要があります。これを行う方法の手がかりはありません。アイデアをください。

更新:

これが私がやっていることです:

UIView *baseView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 200)];
baseView.backgroundColor = [UIColor grayColor];
[window addSubview:baseView];

UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 100, 30)];
textView.autoresizingMask = UIViewAutoresizingFlexibleHeight;
textView.text = @"asdf askjalskjalksjlakjslkasj";
[textView sizeToFit];
[baseView addSubview:textView];
26
saikamesh

setFrame:またはsizeToFitを使用できます。

更新:

私はsizeToFitUILabelと一緒に使用していますが、正常に機能しますが、UITextViewUIScrollViewのサブクラスであるため、sizeToFitが目的の結果を生成しない理由を理解できます。

テキストの高さを計算してsetFrameを使用することもできますが、テキストが長すぎる場合はUITextViewのスクロールバーを利用することもできます。

テキストの高さを取得する方法は次のとおりです。

#define MAX_HEIGHT 2000

NSString *foo = @"Lorem ipsum dolor sit amet.";
CGSize size = [foo sizeWithFont:[UIFont systemFontOfSize:14]
              constrainedToSize:CGSizeMake(100, MAX_HEIGHT)
                  lineBreakMode:UILineBreakModeWordWrap];

そして、これをUITextViewで使用できます。

[textView setFont:[UIFont systemFontOfSize:14]];
[textView setFrame:CGRectMake(5, 30, 100, size.height + 10)];

または、最初に高さの計算を行い、setFrame行を避けます。

UITextView *textView = [[UITextView alloc] initWithFrame:CGRectMake(5, 30, 100, size.height + 10)];
29
Can Berk Güder

ITextViewをそのコンテンツに合わせてサイズ設定するにはどうすればよいですか? に回答が投稿されています。

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

以上(kpowerのコメントによるcontentInsetの考慮)

CGRect frame = _textView.frame;
UIEdgeInsets inset = textView.contentInset;
frame.size.height = _textView.contentSize.height + inset.top + inset.bottom;
_textView.frame = frame;

注:オブジェクトのプロパティを何度も参照する場合(例:frameまたはcontentInset)、ローカル変数に割り当てて、余分なメソッド呼び出しをトリガーしないようにすることをお勧めします(_textView.frame/[_ textView frame] are method呼び出し)。このコードを何度も(10万回)呼び出す場合、これは著しく遅くなります(十数個程度のメソッド呼び出しは重要ではありません)。

しかし...余分な変数なしでこれを1行で実行したい場合は、

        _textView.frame = CGRectMake(_textView.frame.Origin.x, _textView.frame.Origin.y, _textView.frame.size.width, _textView.contentSize.height + _textView.contentInset.top + _textView.contentInset.bottom);

5つの追加のメソッド呼び出しを犠牲にして。

58
Gabe

textViewDidChangetextView.contentSize.heightはサイズ変更のみ可能変更後テキストは実際に大きくなります。最良の視覚結果を得るには、事前にサイズを変更することをお勧めします。数時間後、私はそれをInstagramと完全に同じにする方法を見つけました(それはすべてのBTWの中で最高のアルゴリズムを持っています)

これで初期化:

    // Input
    _inputBackgroundView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, size.height - _InputBarHeight, size.width, _InputBarHeight)];
    _inputBackgroundView.autoresizingMask = UIViewAutoresizingNone;
   _inputBackgroundView.contentMode = UIViewContentModeScaleToFill;
    _inputBackgroundView.userInteractionEnabled = YES;
    [self addSubview:_inputBackgroundView];
   [_inputBackgroundView release];

   [_inputBackgroundView setImage:[[UIImage imageNamed:@"Footer_BG.png"] stretchableImageWithLeftCapWidth:80 topCapHeight:25]];

    // Text field
    _textField = [[UITextView alloc] initWithFrame:CGRectMake(70.0f, 0, 185, 0)];
   _textField.backgroundColor = [UIColor clearColor];
    _textField.delegate = self;
   _textField.contentInset = UIEdgeInsetsMake(-4, -2, -4, 0);
   _textField.showsVerticalScrollIndicator = NO;
   _textField.showsHorizontalScrollIndicator = NO;
    _textField.font = [UIFont systemFontOfSize:15.0f];
    [_inputBackgroundView addSubview:_textField];
   [_textField release];

   [self adjustTextInputHeightForText:@""];

UITextViewデリゲートメソッドを入力します。

- (void) textViewDidBeginEditing:(UITextView*)textView {

   [self adjustTextInputHeightForText:_textField.text];
}

- (void) textViewDidEndEditing:(UITextView*)textView {

   [self adjustTextInputHeightForText:_textField.text];
}

- (BOOL) textView:(UITextView*)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString*)text {

   if ([text isEqualToString:@"\n"])
   {
      [self performSelector:@selector(inputComplete:) withObject:nil afterDelay:.1];
      return NO;
   }
   else if (text.length > 0)
   {
      [self adjustTextInputHeightForText:[NSString stringWithFormat:@"%@%@", _textField.text, text]];
   }
   return YES;
}

- (void) textViewDidChange:(UITextView*)textView {

   [self adjustTextInputHeightForText:_textField.text];
}

そしてトリックは...

- (void) adjustTextInputHeightForText:(NSString*)text {

   int h1 = [text sizeWithFont:_textField.font].height;
   int h2 = [text sizeWithFont:_textField.font constrainedToSize:CGSizeMake(_textField.frame.size.width - 16, 170.0f) lineBreakMode:UILineBreakModeWordWrap].height;

   [UIView animateWithDuration:.1f animations:^
   {
      if (h2 == h1)
      {
         _inputBackgroundView.frame = CGRectMake(0.0f, self.frame.size.height - _InputBarHeight, self.frame.size.width, _InputBarHeight);
      }
      else
      {
         CGSize size = CGSizeMake(_textField.frame.size.width, h2 + 24);
         _inputBackgroundView.frame = CGRectMake(0.0f, self.frame.size.height - size.height, self.frame.size.width, size.height);
      }
      CGRect r = _textField.frame;
      r.Origin.y = 12;
      r.size.height = _inputBackgroundView.frame.size.height - 18;
      _textField.frame = r;

   } completion:^(BOOL finished)
   {
      //
   }];
}
2
m8labs

sizeToFitが機能する

テキストを初めてサイズ変更した後でsizeToFitを呼び出すと、サイズが変更されます。したがって、最初に設定した後は、後続のテキスト設定呼び出しでサイズが変化することはありません。 sizeToFitを呼び出しても。

ただし、次のように強制的にサイズを変更することができます。

  1. テキストを設定します。
  2. TextViewフレームの高さをCGFLOAT_MAXに変更します。
  3. SizeToFitを呼び出します。

これは私にとって完璧に機能します:

    #define MAX_HEIGHT 2000     
    CGSize size = [text sizeWithFont:[UIFont systemFontOfSize:14]
          constrainedToSize:CGSizeMake(100, MAX_HEIGHT)
              lineBreakMode:UILineBreakModeWordWrap];

    [textview setFont:[UIFont systemFontOfSize:14]];
    [textview setFrame:CGRectMake(45, 6, 100, size.height + 10)];
    textview.text = text;
1
Viggnesh

@Gabeによって与えられた答えは、viewDidAppearの後まで一見iOS7.1では機能しません。以下の私のテストを参照してください。

更新:実際には、状況はさらに複雑です。 iOS7では、resizeTheTextViewメソッドでtextView.textを割り当てると、サイズ変更は1行のテキストのみを許可することになります。本当に奇妙です。

UPDATE2:参照 iOS7ではUITextViewコンテンツサイズが異なる

UPDATE3:現在使用しているものについては、一番下のコードを参照してください。仕事をするようです。

#import "ViewController.h"

@interface ViewController ()
{
    UITextView *textView;
}
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    textView = [[UITextView alloc] initWithFrame:CGRectMake(50, 50, 200, 1)];
    [self.view addSubview:textView];
    CALayer *layer = textView.layer;
    layer.borderColor = [UIColor blackColor].CGColor;
    layer.borderWidth = 1;

    textView.text = @"hello world\n\n";

    // Calling the method directly, after the view is rendered, i.e., after viewDidAppear, works on both iOS6.1 and iOS7.1
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    [button setTitle:@"Change size" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(resizeTheTextView) forControlEvents:UIControlEventTouchUpInside];
    [button sizeToFit];
    CGRect frame = button.frame;
    frame.Origin.y = 400;
    button.frame = frame;
    [self.view addSubview:button];

    // Works on iOS6.1, but does not work on iOS7.1
    //[self resizeTheTextView];
}

- (void) viewWillAppear:(BOOL)animated
{
    // Does not work on iOS7.1, but does work on iOS6.1
    //[self resizeTheTextView];
}

- (void) viewDidAppear:(BOOL)animated
{
    // Does work on iOS6.1 and iOS7.1
    //[self resizeTheTextView];
}

- (void) resizeTheTextView
{
    NSLog(@"textView.frame.size.height: %f", textView.frame.size.height);

    NSLog(@"textView.contentSize.height: %f", textView.contentSize.height);

    // 5) From https://stackoverflow.com/questions/728704/resizing-uitextview
    CGRect frame = textView.frame;
    UIEdgeInsets inset = textView.contentInset;
    frame.size.height = textView.contentSize.height + inset.top + inset.bottom;
    textView.frame = frame;

    NSLog(@"inset.top: %f, inset.bottom: %f",  inset.top,  inset.bottom);

    NSLog(@"textView.frame.size.height: %f", textView.frame.size.height);

    NSLog(@"textView.contentSize.height: %f", textView.contentSize.height);
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

UPDATE3:

if ([[UIDevice currentDevice] majorVersionNumber] < 7.0) {
    CGRect frame = _abstractTextView.frame;
    UIEdgeInsets inset = _abstractTextView.contentInset;
    frame.size.height = _abstractTextView.contentSize.height + inset.top + inset.bottom;
    _abstractTextView.frame = frame;
}
else {
    CGSize textViewSize = [_abstractTextView sizeThatFits:CGSizeMake(_abstractTextView.frame.size.width, FLT_MAX)];
    _abstractTextView.frameHeight = textViewSize.height;
}
0
Chris Prince

以下をせよ:

_textView.text = someText;
[_textView sizeToFit];
_textView.frame.height = _textView.contentSize.height;
0
Dat Tran

scrollEnabledNOに設定するか、IBの[Scroll View]セクションでScrolling Enabledのチェックを外すと、UITextViewのサイズが自動調整されます。

0
Mojo66

UITextViewを親に追加した後、コンテンツモードを設定の場合、UITextViewは自動的にサイズを変更するようです。

つまり、高さを手動で計算して高さの制約を適用する必要はありません。うまくいくようです!! iPadのiOS7およびiOS8でテスト済み。

例えば.

--
textView.contentMode = UIViewContentMode.Center;
--

これが機能する理由を誰かが説明できれば、それは非常に高く評価されます..インターフェイスビルダーのオプションをいじっているときに偶然見つけました。

0
Dave Haigh

同様の問題に対処するために、自動レイアウトベースの軽量UITextViewサブクラスを作成しました。これは、ユーザー入力のサイズに基づいて自動的に拡大および縮小し、最大および最小の高さによって制約を受けることができます。すべて1行のコードは必要ありません。

https://github.com/MatejBalantic/MBAutoGrowingTextView

0
Matej Balantič