Как изменить размер UITextView при вводе внутри него?

Я создаю раздел комментариев, очень похожий на тот, который Facebook использует для обмена сообщениями в приложении для iOS. Я хочу, чтобы UITextView изменил размер по высоте, чтобы текст, который я набираю, помещался внутри него, вместо того, чтобы вам приходилось прокручивать, чтобы увидеть текст, который выходит за пределы. Есть идеи, как я могу это сделать? Я рассмотрел, возможно, использование CGRect, который назначается размеру и высоте текстового представления, которое затем соответствует размеру содержимого:

CGRect textFrame = textView.frame;
textFrame.size.height = textView.contentSize.height;
textView.frame = textFrame;

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


person Ollie177    schedule 21.11.2012    source источник
comment
Вы можете найти подробное рабочее решение здесь   -  person malex    schedule 04.06.2016


Ответы (5)


Вы можете настроить фрейм в этом методе делегата, не забудьте установить делегат textView на себя.

-(BOOL)textView:(UITextView *)_textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text {
      [self adjustFrames];  
      return YES;
}


-(void) adjustFrames
{
   CGRect textFrame = textView.frame;
   textFrame.size.height = textView.contentSize.height;
   textView.frame = textFrame;
}

это решение предназначено для iOS6 и более ранних версий ... для iOS7 см. это

Ответ StackOverflow

person waheeda    schedule 21.11.2012
comment
Да неужели? Я не думал, что это будет так просто ... хорошо, спасибо, я попробую! - person Ollie177; 21.11.2012
comment
чтобы заставить работать в iOS 7+, добавьте adjustFrames в - (void)textViewDidChange:(UITextView *)textView - person Fahim Parkar; 14.09.2017

Это мое решение, использующее autolayout и textView.contentSize.height. Проверено на iOS8 Xcode6.3 beta4.

Есть одна загвоздка в setContentOffset в конце. Я поставил это, чтобы избежать артефакта "неправильный contentOffset" при изменении количества строк. Он добавляет лишнее нежелательное пустое пространство под последней строкой и выглядит не очень хорошо, если вы не установите его обратно сразу после изменения ограничения. Мне потребовались часы, чтобы понять это!

// set this up somewhere
let minTextViewHeight: CGFloat = 32
let maxTextViewHeight: CGFloat = 64

func textViewDidChange(textView: UITextView) {

    var height = ceil(textView.contentSize.height) // ceil to avoid decimal

    if (height < minTextViewHeight + 5) { // min cap, + 5 to avoid tiny height difference at min height
        height = minTextViewHeight
    }
    if (height > maxTextViewHeight) { // max cap
        height = maxTextViewHeight
    }

    if height != textViewHeight.constant { // set when height changed
        textViewHeight.constant = height // change the value of NSLayoutConstraint
        textView.setContentOffset(CGPointZero, animated: false) // scroll to top to avoid "wrong contentOffset" artefact when line count changes
    }
}
person Hlung    schedule 06.04.2015
comment
где заявлен textViewHeight? - person lf215; 22.09.2016
comment
@ lf215 это объект NSLayoutConstraint для высоты UITextView. Забыл добавить извините. - person Hlung; 22.09.2016
comment
Я новичок в этом. Не могли бы вы уточнить / добавить дополнительный код, чтобы показать, как получить textViewHeight? - person lf215; 22.09.2016
comment
@ lf215 Если вы используете раскадровку, то это будет переменная IBOutlet, такая как @IBOutlet weak var textViewHeight: NSLayoutConstraint!, которую вы подключаете к ограничению высоты вашего UITextView в построителе интерфейса. - person Hlung; 28.09.2016
comment
у меня это работает очень хорошо, и я счастлив, но мне интересно, есть ли что-то маленькое, что я мог бы изменить, чтобы сделать его еще лучше. курсор всегда кажется центрированным по вертикали. это хорошо выглядит с одной строкой: dropbox.com/s/dwjbjhcm80a6co5/Screenshot%202016-09-28%2022.54.10.png, но не очень хорошо с двумя строками: dropbox.com/s/7216694bohuqfin/ в идеале вторая строка должна оставаться плоской внизу. Я предполагаю, что это из-за вертикального центрирования курсора. - person lf215; 29.09.2016
comment
У меня это почти сработало, но мне пришлось добавить эту строку между установкой ограничения и смещением содержимого: textView.bounds.size.height = textView.contentSize.height. Также я заметил, что использование textView.contentOffset = CGPointZero не работает. - person Nickkk; 12.01.2017

В TableViewController, который содержит UITextView, обновите данные из tableViewDataSource, который помещается в ячейку, а затем просто вызовите это:

tableView.beginUpdates()
tableView.endUpdates()

В отличие от tableView.reloadData (), это не вызывает resignFirstResponder

person Bart Herrijgers    schedule 01.06.2017
comment
Это потрясающе! Спасибо. Вот то же самое в ObjC: - (void)textViewDidChange:(UITextView *)textView { [self.tableView beginUpdates]; [self.tableView endUpdates]; } Даже анимацию получаете бесплатно;) - person Holtwick; 27.02.2018

Сначала установите ограничения минимальной высоты для TextView:

textView.heightAnchor.constraint(greaterThanOrEqualTo: view.heightAnchor, multiplier: 0.20)

(Убедитесь, что вы устанавливаете ограничение большеThanOrEqualTo, чтобы, если внутренняя высота содержимого больше, чем эта высота, она принимает внутреннюю высоту содержимого)

ИЛИ простая константа

textView.heightAnchor.constraint(greaterThanOrEqualToConstant: someConstant)

При настройке вашего textView установите isScrollEnabled в false

textView.isScrollEnabled = false

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

person atish vishwakarma    schedule 13.09.2017

contentsize не будет работать в ios 7. Попробуйте следующее:

CGFloat textViewContentHeight = textView.contentSize.height;

 textViewContentHeight = ceilf([textView sizeThatFits:textView.frame.size].height + 9);
person gunas    schedule 27.01.2014