SWIFT如何调整textview的高度到他的内容?

How to adjust the height of a textview to his content in SWIFT?

在我的视图控制器中,我有一个 UITextView。这个文本视图填充了一个字符串。字符串可以很短也可以很长。根据字符串的长度,文本视图的高度必须进行调整。 我使用故事板和自动布局。

我对 textview 的高度有一些问题。

有时,高度会完美地适应文本。有时,不,文本在第一行被裁剪。下面,textview 是黄色的。蓝色是滚动视图内的容器视图。紫色是拍照的地方。

文本来自我的核心数据库,它们是字符串属性。 在屏幕 1 和屏幕 2 之间,唯一改变的是字符串。
如果我在控制台中打印字符串,我就会得到正确的文本:

my amazing new title

Another funny title for demo

我的 textview 的限制:

我不明白为什么我有 2 个不同的显示器。

编辑

我尝试了@Nate 的建议,在 viewDidLoad 中,我添加了:

    myTextViewTitle.text="my amazing new title"

    myTextViewTitle.setContentHuggingPriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setContentCompressionResistancePriority(1000, forAxis: UILayoutConstraintAxis.Vertical)
    myTextViewTitle.setTranslatesAutoresizingMaskIntoConstraints(false)  

    let views = ["new_view": myTextViewTitle]
    var constrs = NSLayoutConstraint.constraintsWithVisualFormat("|-8-[new_view]-8-|", options: NSLayoutFormatOptions(0), metrics: nil, views: views)
    self.view.addConstraints(constrs)
    self.view.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-8-[new_view]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))
    self.myTextViewTitle.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:[new_view(220@300)]", options: NSLayoutFormatOptions(0), metrics: nil, views: views))

没有结果。在界面生成器中为我的文本视图添加或不添加高度限制...

编辑 2

我需要一个 UITextView 而不是 UIlabel,因为有后退按钮,才能使用排除路径。

     let exclusionPathBack:UIBezierPath = UIBezierPath(rect: CGRect(x:backButton.bounds.origin.x, y:backButton.bounds.origin.y, width:backButton.bounds.width+10, height:backButton.bounds.height))
     myTextViewTitle.textContainer.exclusionPaths=[exclusionPathBack]

为什么不用后退按钮的图像和文本的 UILabel,并使用自动布局来定位它们?也许还有黄色背景的第三个视图。

我找到了解决办法。

我关注的是我的 UITextView 的高度,然后我读了一篇 post 谈论纵横比的文章。我想尝试一下,结果成功了!

所以在情节提要中,我为文本视图添加了纵横比,并选中了 "Remove at build time" 选项。

在viewDidLayoutSubviews()中,我写了:

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()

    let contentSize = self.myTextViewTitle.sizeThatFits(self.myTextViewTitle.bounds.size)
    var frame = self.myTextViewTitle.frame
    frame.size.height = contentSize.height
    self.myTextViewTitle.frame = frame

    aspectRatioTextViewConstraint = NSLayoutConstraint(item: self.myTextViewTitle, attribute: .Height, relatedBy: .Equal, toItem: self.myTextViewTitle, attribute: .Width, multiplier: myTextViewTitle.bounds.height/myTextViewTitle.bounds.width, constant: 1)
    self.myTextViewTitle.addConstraint(aspectRatioTextViewConstraint!)

}

完美运行。

我对一个极其相似问题的简单解决方案:

我使用了行数设置为 0 的标签,而不是尝试使用文本字段或视图。然后我将前缘和后缘剪裁到标签的容器中,在我的例子中,它们限制了它们的宽度,0 作为约束的常量。要注意的是将行数设置为 0,以允许标签根据其内容增长或收缩。对于我为宽度配置的所有不同大小 类(在我的例子中是容器宽度),文本永远不会被截断并且标签的高度永远不会超过它们的内容。针对 IOS 8.0 及更高版本进行了测试(还要确保在所有标签的 'Preferred Width' 属性旁边取消选中 'explicit',以便标签宽度根据不同大小进行调整 类)- 完美运行.

首先,禁用 UITextView 的可滚动。 两个选项:

  1. 取消选中在 .xib 中启用滚动。
  2. [TextView setScrollEnabled:NO];

创建一个 UITextView 并将其与 IBOutlet (TextView) 连接。 添加默认高度的 UITextView 高度约束,将其与 IBOutlet (TextViewHeightConstraint) 连接。 当您异步设置 UITextView 的文本时,您应该计算 UITextView 的高度并将 UITextView 的高度约束设置为它。 示例代码:

CGSize sizeThatFitsTextView = [TextView sizeThatFits:CGSizeMake(TextView.frame.size.width, MAXFLOAT)];

TextViewHeightConstraint.constant = sizeThatFitsTextView.height; 

在swift 2.3:

 func textViewDidChange(textView: UITextView) {

    let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.max))
    if size.height != TXV_Height.constant && size.height > textView.frame.size.height{
        TXV_Height.constant = size.height
        textView.setContentOffset(CGPointZero, animated: false)
    }
}

在Swift 3.0 中,其中 tvHeightConstraint 是主题 TextView 的高度约束(如果用于多个文本视图,会将其添加到函数输入中):

func textViewDidChange(textView: UITextView) {

        let size = textView.sizeThatFits(CGSize(width: textView.frame.size.width, height: CGFloat.greatestFiniteMagnitude))
        if size.height != tvHeightConstraint.constant && size.height > textView.frame.size.height{
            tvHeightConstraint.constant = size.height
            textView.setContentOffset(CGPoint.zero, animated: false)
        }
    }

H/T @cmi 和@Pablo Ruan

我已经修改了您的代码并将其用于:布局子视图和 textViewDidChange。非常感谢你让我在一个小时的故障排除后度过了愉快的一天...

override func viewDidLayoutSubviews() {

    super.viewDidLayoutSubviews()
    textViewDidChange(self.recordingTitleTV)


}

func textViewDidChange(_ textView: UITextView) {

    let contentSize = textView.sizeThatFits(textView.bounds.size)
    var frame = textView.frame
    frame.size.height = contentSize.height
    textView.frame = frame

    let aspectRatioTextViewConstraint = NSLayoutConstraint(item: textView, attribute: .height, relatedBy: .equal, toItem: textView, attribute: .width, multiplier: textView.bounds.height/textView.bounds.width, constant: 1)
    textView.addConstraint(aspectRatioTextViewConstraint)
}