Изменение размера UITextView - PullRequest
26 голосов
/ 08 апреля 2009

У меня 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];

Ответы [ 10 ]

58 голосов
/ 17 мая 2010

Ответ опубликован на Как мне настроить 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 дополнительных вызовов методов.

29 голосов
/ 08 апреля 2009

Вы можете использовать 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 голосов
/ 07 августа 2013

sizeToFit работает

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

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

  1. Установить текст.
  2. Измените высоту кадра textView на CGFLOAT_MAX.
  3. Call sizeToFit.
2 голосов
/ 04 ноября 2012

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)
   {
      //
   }];
}
1 голос
/ 20 июля 2011

Это прекрасно работает для меня:

    #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;
0 голосов
/ 10 апреля 2018

Просто установите scrollEnabled на NO или снимите флажок Прокрутка включена в разделе «Просмотр прокрутки» в IB, и UITextView будет иметь собственный размер.

0 голосов
/ 07 сентября 2015

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

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

*

например, 1007 *

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

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

0 голосов
/ 05 июня 2014

Ответ, данный @Gabe, не работает в iOS7.1, по-видимому, до окончания viewDidAppear. Смотрите мои тесты ниже.

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

ОБНОВЛЕНИЕ2: См. Также Размер содержимого UITextView отличается в iOS7

ОБНОВЛЕНИЕ 3: Смотрите мой код в самом низу для того, что я использую сейчас. Кажется, чтобы сделать работу.

#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 /554000/izmenenie-razmera-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 голосов
/ 16 мая 2014

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

https://github.com/MatejBalantic/MBAutoGrowingTextView

0 голосов
/ 30 сентября 2013

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

_textView.text = someText;
[_textView sizeToFit];
_textView.frame.height = _textView.contentSize.height;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...