Высота автоматического макета 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().

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