Подтвердить что ты не робот

Изменение размера UITextView

У меня есть UITextView, добавленный в мой UIView. Текстовое добавление не редактируется, это просто отображение некоторых данных. Данные, отображаемые в текстовом режиме, являются динамическими. То есть количество строк не фиксировано. Он может меняться. Поэтому, если число строк увеличивается, размер текста также необходимо увеличить. Я не знаю, как это сделать. Пожалуйста, дайте мне несколько идей.

UPDATE:

Вот что я делаю:

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];
4b9b3361

Ответ 1

Вы можете использовать setFrame: или sizeToFit.

UPDATE:

Я использую sizeToFit с UILabel, и он отлично работает, но UITextView является подклассом UIScrollView, поэтому я могу понять, почему 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)];

Ответ 2

Есть ответ, отправленный в Как настроить UITextView для его содержимого?

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

или лучше (с учетом contentInset благодаря комментарию kpower)

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 ] - вызовы методов). Если вы вызываете этот код много (100000 раз), это будет заметно медленнее (десятки или около того вызовов метода несущественны).

Однако... если вы хотите сделать это в одной строке без дополнительных переменных, это будет

        _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 вызовов дополнительных методов.

Ответ 3

textView.contentSize.height в textViewDidChange может изменяться только после того, как текст действительно растет. Для лучшего визуального результата лучше изменить размер заранее. Через несколько часов я выяснил, как сделать это так же отлично, как в 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)
   {
      //
   }];
}

Ответ 4

sizeToFit Does Work

Если вы вызываете sizeToFit после того, как вы установите текст при первом изменении размера. Поэтому после того, как вы впервые установили его последующие вызовы для установки текста, это не приведет к изменению размера. Даже если вы вызываете sizeToFit.

Однако вы можете заставить его изменить размер следующим образом:

  • Установите текст.
  • Измените высоту кадра textView на CGFLOAT_MAX.
  • Вызов sizeToFit.

Ответ 5

Это отлично работает для меня:

    #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;

Ответ 6

Выполните следующие действия:

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

Ответ 7

Обращаясь к подобной проблеме, я просто создал легкий подкласс UITextView на основе автоматической компоновки, который автоматически растет и сжимается в зависимости от размера ввода пользователя и может быть ограничен максимальной и минимальной высотой - все без единой строки кода.

https://github.com/MatejBalantic/MBAutoGrowingTextView

Ответ 8

Ответ, данный @Gabe, не работает в iOS7.1, казалось бы, до появления viewDidAppear. См. Мои тесты ниже.

ОБНОВЛЕНИЕ: На самом деле ситуация еще сложнее. Если вы назначаете textView.text в методе resizeTheTextView, в iOS7 размер изменения составляет только одну строку текста. Серьезно странно.

UPDATE2: См. также Размер содержимого UITextView, отличный от iOS7

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

Ответ 9

После добавления UITextView к его родительскому элементу, если вы установите режим содержимого, то он автоматически изменит размер.

Это означает, что вам не нужно вручную определять высоту и применять ограничение высоты. Кажется, это работает! Протестировано в iOS7 и iOS8 на iPad.

например.

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

Если кто-нибудь может объяснить, почему это работает, это было бы очень признательно. Я случайно обнаружил это, когда возился с параметрами в построителе интерфейса.