Как принудительно расположить глифы, расположенные далеко за пределами вертикальных границ UITextView?

#swift #uiscrollview #uitextview #cgrect

#swift #uiscrollview #uitextview #cgrect

Вопрос:

Здесь код не нужен. Мне нужно некоторое руководство о том, как расположить все глифы очень длинной многострочной строки, которые будут отображаться в UITextView с включенной прокруткой. Некоторая справочная информация для понимания обстоятельств.

Предыстория: у меня очень длинный многострочный текст, который необходимо представить в UITextView с включенной прокруткой. Я создал функцию, которая определяет CGRect позицию совпадения строки поиска в многострочной строке, а затем анимирует пользователя до CGRect позиции совпадения. Это достигается путем передачи CGRect соответствующего текста contentOffset , который анимирует прокрутку, в нужное место. CGRect Переданный в contentOffset генерируется с использованием layoutmanager для обеспечения точности. Другими словами, CGRect расположение текста зависит от положения символа соответствующей строки.

Однако, если CGRect соответствующая строка поиска расположена вертикально далеко от UITextView bounds.height , анимация фактически завершается неудачей. Прокрутки вообще нет. Как будто анимация прокрутки не знает, где найти CGRect позицию для прокрутки до соответствующей строки. Я могу исправить проблему, если сначала вручную прокрутить до самого низа UITextView, а затем выполнить анимацию до CGRect позиции соответствующей строки поиска. При таких обстоятельствах UITextView как будто имеет полную картину расположения текста и может точно найти местоположение соответствующей строки поиска CGRect в многострочной строке.

Исходя из вышеизложенного, для меня очевидно, что UITextView не размещает все глифы многострочной строки сразу. Представление, вероятно, рисует глифы фрагментами, аналогично тому, как табличное представление создает ячейки. Мне также кажется, что UITextView имеет возможность сохранять всю информацию о макете глифа, когда я вручную прокручиваю границы представления до самого низа вертикального размера содержимого.

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

Комментарии:

1. Что не так с UITextView scrollRangeToVisible методом?

2. Роб — Да, scrollRangeToVisible знает, где найти совпадение. Однако функция имеет встроенную анимацию, которая конфликтует с анимацией, которую я запускаю. Я могу отключить встроенную анимацию scrollRangeToVisible. Существует проблема: в моей последовательности анимации также используется подвиде, прямоугольник с границей размером соответствующего текста. Вложенное представление анимируется с помощью прокрутки и обводит соответствующий текст, чтобы служить визуальной подсказкой. В подвиде используется CGRect глифа. Вложенный вид тоже теряется. scrollRangeToVisible не предоставляет решения для размещения вложенного представления в правильном месте.

3. Вы проверили, что текстовое представление contentSize достаточно велико, чтобы вместить ваше CGRect , прежде чем пытаться прокручивать? Возможно contentSize , он не обновляется должным образом, если вы запускаете дополнительный инкрементный макет вне контроля текстового представления.

4. Не напрямую. Я проверяю, находится ли прямоугольник последнего совпадения (я увеличиваю через массив совпадений) в пределах textview. Если false, то пользователь имеет возможность увеличивать массив совпадений нажатием кнопки, которая инициирует последовательность анимации, описанную выше. Короче говоря, анимация недоступна, если совпадение не находится за пределами textview. Ошибка возникает, когда сопоставленный текст находится на очень большом расстоянии от границ textview.

5. Роб — Как я думаю о вашем предложении, каждый раз, когда я обращаюсь contenSize , я получаю полный размер до запуска анимации. Должен быть какой-то объект, который можно обновить, чтобы предоставить необходимую информацию о макете. Как scrollRangeToVisible выполняет задачу?

Ответ №1:

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

Например, если у вас достаточно текста в текстовом представлении, чтобы охватить видимую область, в 10 раз превышающую видимую, UIKit может «повременить» с размещением текста. В конце концов, только потому, что текст есть, это не значит, что пользователь когда-либо будет прокручивать его.

NSLayoutManager предоставляет несколько функций, которые позволяют вам убедиться, что все содержимое вашего текстового представления выложено, когда вы хотите получить к нему доступ (см. https://developer.apple.com/documentation/uikit/nslayoutmanager ):

 func ensureGlyphs(forCharacterRange: NSRange)
func ensureGlyphs(forGlyphRange: NSRange)
func ensureLayout(forBoundingRect: CGRect, in: NSTextContainer)
func ensureLayout(forCharacterRange: NSRange)
func ensureLayout(forGlyphRange: NSRange)
func ensureLayout(for: NSTextContainer)
  

Согласно комментариям OP, вызов .ensureLayout viewDidLayoutSubviews() решил проблему.

Комментарии:

1. Спасибо, что нашли время подумать над этим вопросом. Очень признателен.