Запретить UITextView смещать свой текстовый контейнер

Я пытаюсь изменить высоту UITextView динамически (до максимальной высоты), пока пользователь вводит текст. Я испытываю очень странное поведение, когда в текстовом представлении четное количество строк.

Я использую autolayout, и текстовое представление имеет ограничение по высоте. Я отвечаю на звонки делегату текстового представления (textViewDidChange(_:)), где я рассчитываю и корректирую ограничение высоты на основе contentSize,

Вот код:

func textViewDidChange(_ textView: UITextView) {
    let newHeight = textView.contentSize.height
    let newConstraintConst = max(MinTextViewHeight, min(MaxTextViewHeight, newHeight))
    self.textViewHeightConstraint.constant = newConstraintConst
}

Это хорошо работает, он изменяет размер кадра до MaxTextViewHeight а затем текстовое представление можно прокручивать. Однако, когда в текстовом представлении есть четное количество строк, текстовое представление добавляет своего рода смещение к нижней части его NSTextContainer, в результате чего верхняя строка обрезается:

верхняя линия отрезана

текстовый контейнер смещен

Однако, когда есть нечетные строки, NSTextContainer больше не смещено:

верхняя строка нормальная

текстовый контейнер нормальный

Сначала я думал, что это каким-то образом контролируется текстовым представлением textContainerInset но это используется только для заполнения пространства внутри NSTextContainer, как установить его в .zero удаляет пространство внутри, но не влияет на смещение (и, кстати, делает его еще хуже, так как верхняя линия почти полностью исчезает):

удаление вставки делает это еще хуже

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

В качестве обходного пути я увеличиваю верхнюю вставку текстового контейнера и удаляю нижнюю вставку:

textView.textContainerInset = UIEdgeInsetsMake(10, 0, 0, 0)

Пока это работает, но я пришел к значению 10 методом проб и ошибок, и до сих пор я тестировал его только на одном устройстве.

Меня не интересуют более хакерские обходные пути, которые требуют хрупких фиксированных значений; Я пытаюсь понять, как устанавливается это смещение и как его исправить. Я надеюсь, что кто-то может дать некоторое представление, спасибо!

1 ответ

Решение

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

Не уверен, если вы думаете, что мое решение слишком хакерское, но это остановит его от прокрутки, когда вы этого не хотите. Я просто прикрепляю смещение контента к верху, если требуемый размер контента меньше вашего максимального размера.

Просто добавьте это:

func scrollViewDidScroll(scrollView: UIScrollView) {
    if textView.contentSize.height <= MaxTextViewHeight && textView.contentOffset.y > 0.0 {
        textView.contentOffset.y = 0.0;
    }

}
Другие вопросы по тегам