使用排除路径

时间:2017-06-14 20:28:55

标签: ios uitextview nslayoutconstraint ios-autolayout exclusionpath

我有一个包含UITextView和UIImageView的UITableViewCell。文本视图已禁用滚动。 UITableViewCell确实使用自动布局来计算其高度以适应内容。

view layout screenshot

如果文字比截图中的文字多,我希望文字在图像周围流动并使用下面的空间。因此,我在文本视图上使用排除路径。排除路径设置正确,文本在图像周围流动。

必须在自动布局计算框架后设置排除路径。由于排除路径会阻止文本视图中的某些视图空间在为文本视图计算的高度自动布局中包含的文本不再适合

如何与自动布局一起使用?

设置排除路径后,我尝试在文本视图上设置高度约束:

    let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat(MAXFLOAT)))
    textView.heightAnchor.constraint(equalToConstant: size.height).isActive = true

这没有用。我需要在UITableViewCell上调用layoutSubviews()来强制它重新计算它的高度。但是,当我在viewDidLayoutSubviews()中设置排除路径时,这将创建一个无限循环。

2 个答案:

答案 0 :(得分:0)

我有一个类似的问题,我无法在没有过多耦合的情况下访问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.
}

这类似于之前iOS版本中使用UILabel和maxPreferredWidth的方法。 iOS: Multi-line UILabel in Auto Layout

有一点需要注意:我不知道在这里设置约束会对你有所帮助,因为布局周期确实不会那样,但根据这个Update Constraints of Cell Subview,你可能会能够摆脱layoutIfNeeded()。

答案 1 :(得分:0)

我发现,当UITextViewintrinsicContentSize并且isScrollEnabled发生变化时,false不会重新计算textContainer.exclusionPaths

解决方案很简单:

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