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


person funkenstrahlen    schedule 14.06.2017    source источник
comment
В UIView есть специальная функция, которая обновляет ограничения. Может быть, попробуйте переопределить это так: override func updateConstraints() { super.updateConstraints() let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat(MAXFLOAT))) textView.heightAnchor.constraint(equalToConstant: size.height).isActive = true }   -  person Eugene Dudnyk    schedule 15.06.2017


Ответы (2)


У меня была аналогичная проблема, когда я не мог получить доступ к 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 в автоматическом макете

Одно предостережение: я не знаю, поможет ли вам установка ограничения здесь, поскольку циклы макета на самом деле не работают таким образом, но в соответствии с этим Update Constraints of Cell Subview , возможно, вам удастся обойтись без layoutIfNeeded().

person jimmynotjames    schedule 01.08.2017

Я обнаружил, что UITextView НЕ пересчитывает intrinsicContentSize, когда isScrollEnabled равно false, а textContainer.exclusionPaths меняется.

Решение было простым:

class FixedTextView : UITextView {
    
    func setExclusionPaths(_ paths: [UIBezierPath]) {
        textContainer.exclusionPaths = paths
        
        if !isScrollEnabled {
            invalidateIntrinsicContentSize()
        }
    }
}
person ryanholden8    schedule 14.11.2020