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

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

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

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

Ответ 1

Вы можете настроить фрейм в этом методе делегата, не забудьте установить делегат 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 см. этот

fooobar.com/questions/9702/...

Ответ 2

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

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

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

Ответ 3

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

tableView.beginUpdates()
tableView.endUpdates()

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

Ответ 4

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

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

(Убедитесь, что вы устанавливаете ограничение LargeThanOrEqualTo Constraint, чтобы, если высота внутреннего содержимого больше этой высоты, она занимает внутреннюю высоту содержимого)

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

textView.heightAnchor.constraint(greaterThanOrEqualToConstant: someConstant)

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

textView.isScrollEnabled = false

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

Ответ 5

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

CGFloat textViewContentHeight = textView.contentSize.height;

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