ios 如何在SWIFT中将textview的高度调整为他的内容?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/29431968/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 05:29:12  来源:igfitidea点击:

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

iosswiftautolayoutuitextview

提问by cmii

In my view controller, I have an UITextView. This textview is filled with a string. The string can be short or long. Depending on the length of the string, the height of the textview has to adjust. I use storyboards and auto layout.

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

I have some troubles with the height of the textview.

我对 textview 的高度有一些麻烦。

Sometimes, the height is perfectly adjusted to the text. Sometimes, no, the text is cropped on the first line. Below, the textview is yellow. the blue is a containerview inside a scrollview. Purple is the place for a picture.

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

title1title2

标题 1标题2

The texts are from my core data base, they are string attributes. Between the screen 1 and 2, the only thing changed is the string.
If I print the strings in the console I have the correct texts :

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

my amazing new title

Another funny title for demo

The constraints of my textview :

我的 textview 的约束:

enter image description here

enter image description here

I don't understand why I have 2 different displays.

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

EDIT

编辑

I tried the @Nate advice, in viewDidLoad, I added:

我尝试了@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))

No results. With or without height contraint added for my textview in interface builder...

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

EDIT 2

编辑 2

I need an UITextView and not an UIlabel, because of the back button, to use an exclusion path.

由于后退按钮,我需要一个 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]

回答by cmii

I found a solution.

我找到了解决方案。

I was focus on the height of my UITextView, then I read a post talking about the aspect ratio. I wanted to try and that worked!

我专注于 UITextView 的高度,然后我读了一篇关于纵横比的帖子。我想尝试并且奏效了!

So in the storyboard, I added an aspect ratio for the textview, and I checked "Remove at build time" option.

因此,在情节提要中,我为文本视图添加了纵横比,并选中了“在构建时删除”选项。

In viewDidLayoutSubviews(), I wrote :

在 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!)

}

It works perfectly.

它完美地工作。

回答by Сергей Билык

First, disable UITextView's scrollable. Two options:

首先,禁用 UITextView 的可滚动。两种选择:

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

Create a UITextView and connect it with IBOutlet (TextView). Add a UITextView height constraint with default height, connect it with IBOutlet (TextViewHeightConstraint). When you set your UITextView's text asynchronously you should calculate the height of UITextView and set UITextView's height constraint to it. Sample code:

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

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

TextViewHeightConstraint.constant = sizeThatFitsTextView.height; 

回答by agrippa

In Swift 3.0, where tvHeightConstraint is the height constraint of the subject TextView (if using for multiple textviews, would add it to the function inputs):

在 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 to @cmi and @Pablo Ruan

致@cmi 和@Pablo Ruan

回答by Pablo Ruan

In swift 2.3:

在 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)
    }
}

回答by AppNerd

I have adapted your code and used it for both: layout subview and textViewDidChange. Thank you very much that made my day after an hour of troubleshooting...

我已经调整了您的代码并将其用于:布局子视图和 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)
}

回答by koen

Why not have an image for the back button and a UILabel for your text, and use autolayout to position them? And maybe a third view for the yellow background.

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

回答by AshleyC

My simple solution to an extremely similar problem:

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

I used labels with the number of lines set to 0 instead of trying to use text fields or views. Then I clipped the leading and trailing edges to the labels' containers which constrain their widths in my case, with 0 as the constant for the constraints. The catch is to set the number of lines to 0 to allow the labels to grow or shrink according to their content. The text never gets chopped and the height of the labels never exceed their contents' for all of the different size classes I configured for the widths (the container widths in my case). Tested for IOS 8.0 and later (also make sure 'explicit' is unchecked next to 'Preferred Width' attributes for all lables for the label widths to adjust for different size classes) - works perfectly.

我使用了行数设置为 0 的标签,而不是尝试使用文本字段或视图。然后我将前缘和后缘剪裁到标签的容器上,在我的情况下,这些容器限制了它们的宽度,0 作为约束的常量。问题是将行数设置为 0 以允许标签根据其内容增长或缩小。对于我为宽度配置的所有不同尺寸类(在我的情况下为容器宽度),文本永远不会被切碎,标签的高度永远不会超过其内容。针对 IOS 8.0 及更高版本进行了测试(还要确保在所有标签的“首选宽度”属性旁边取消选中“显式”,以便针对不同的尺寸类别进行调整) - 完美运行。