Высота автоматического макета UITextView при использовании пути исключения
У меня есть UITableViewCell, содержащий UITextView и UIImageView. В текстовом представлении прокрутка отключена. UITableViewCell использует автоматическую компоновку, чтобы вычислить его высоту, чтобы соответствовать содержимому.
Если текста больше, чем на скриншоте, я хочу, чтобы текст обтекал изображение и использовал пространство под ним. Поэтому я использую путь исключения в текстовом представлении. Путь исключения устанавливается правильно, и текст обтекает изображение.
Пути исключения должны быть установлены после того, как автоматический макет рассчитал кадры. Поскольку путь исключения блокирует некоторое пространство просмотра в текстовом представлении, содержащий текст больше не помещается в автоматический макет высоты, рассчитанный для текстового представления.
Как я могу заставить это работать вместе с автоматическим макетом?
Я попытался установить ограничение высоты для текстового представления после установки путей исключения:
let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat(MAXFLOAT)))
textView.heightAnchor.constraint(equalToConstant: size.height).isActive = true
Это не помогает. Мне нужно позвонить layoutSubviews()
на UITableViewCell, чтобы заставить его пересчитать его высоту. Однако это создаст бесконечный цикл, так как я устанавливаю свои пути исключения в viewDidLayoutSubviews()
,
1 ответ
Я нашел это
UITextView
НЕ пересчитывает
intrinsicContentSize
когда
isScrollEnabled
является
false
и
textContainer.exclusionPaths
изменения.
Решение было простым:
class FixedTextView : UITextView {
func setExclusionPaths(_ paths: [UIBezierPath]) {
textContainer.exclusionPaths = paths
if !isScrollEnabled {
invalidateIntrinsicContentSize()
}
}
}
У меня была похожая проблема, когда я не мог реально получить доступ к viewDidLayoutSubviews() без чрезмерного связывания, поэтому я чувствую вашу боль.
Предположим, у вас есть представление A и подпредставления включают в себя UITextView.
В представлении A переопределите layoutSubviews()
override public func layoutSubviews() {
super.layoutSubviews()
// At this point, UITextView is laid out and has a valid frame.
// Set exclusion paths here, now that you have enough info to set coordinates.
super.layoutSubviews() // do it again.
}
Это похоже на подход, использованный с UILabel и maxPreferredWidth в предыдущих версиях iOS. iOS: многострочная UILabel в автоматическом макете
Одно предостережение: я не знаю, что установка здесь ограничения поможет вам, так как циклы макета действительно не работают таким образом, но в соответствии с этим Обновлением Ограничений Ячейки Subview, вы можете быть в состоянии уйти с выполнением layoutIfNeeded().