如何根据文本长度使UITextView高度动态?


80

如您在这张图片中看到的

UITextView根据文本长度它的高度的变化,我想让它根据文本长度调节它的高度。

*我看到了其他问题,但是那里的解决方案对我没有用

例



我使用nextGrowingTextView github.com/muukii/NextGrowingTextView我什已经在Objective c上编写了一个实现github.com/mcmatan/NextGrowingInternalTextViewObjectiveC
MCMatan

CSGrowingTextView也是解决此问题的替代方法:github.com/cloverstudio/CSGrowingTextView
Josip B.

确保将拥抱和耐压优先级设置为更低
Ethan SK

这些天是完全自动的-不要忘记禁用滚动。显然,您需要在视图周围(如任何视图)使用正确的约束条件
Fattie

Answers:


139

这个作品对我来说,所有其他解决方案都没有。

func adjustUITextViewHeight(arg : UITextView)
{
    arg.translatesAutoresizingMaskIntoConstraints = true
    arg.sizeToFit()
    arg.scrollEnabled = false
}

在Swift 4中,的语法arg.scrollEnabled = false已更改为arg.isScrollEnabled = false


当文本很大时,当我对scrollEnabled属性设置为假时,文本不会显示。你能帮我吗 ?我的意思是文本在那里,但看不到。
Bhautik Ziniya '17

1
请问一个完整的代码和故事板详细信息的单独问题。
DeyaEldeen

@DeyaEldeen +1,它可以正常工作,我也尝试过使用静态tableview单元,非常好:)
elia

1
并确保在设置.text;)之后设置这些属性。谢谢!
Lahiru Pinto

1
就我而言,仅arg.sizeToFit()就足够了。arg.translatesAutoresizingMaskIntoConstraints删除了我的约束
Niib Fouda

53

在Storyboard / Interface Builder中,只需禁用“属性”检查器中的滚动即可。

在代码中textField.scrollEnabled = false应该可以解决问题。


1
我简直不敢这么简单。我认为这应该是公认的答案。
—אorihpt

26

试试看:

CGRect frame = self.textView.frame;
frame.size.height = self.textView.contentSize.height;
self.textView.frame = frame;

编辑-这是Swift:

var frame = self.textView.frame
frame.size.height = self.textView.contentSize.height
self.textView.frame = frame

好的,谢谢,我也会尝试这个,并告诉您结果。
DeyaEldeen '16

20

斯威夫特4

将其添加到您的班级

UITextViewDelegate

func textViewDidChange(_ textView: UITextView) {
      let fixedWidth = textView.frame.size.width
      textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
      let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
      var newFrame = textView.frame
      newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
      textView.frame = newFrame
}

它可以按我的需要很好地工作。但是textview键盘从第二次起就没有打开,除了第一行。
Shangari C

2
textView.translatesAutoresizingMaskIntoConstraints = true也需要
Ryan

当textview退出第一响应者时,只需调用sizeToFit()即可。
K. Mitra

20

在Xcode 11.2.1,Swift 5.1上进行了测试:

我要做的就是:

  1. 将约束设置为textView的顶部,左侧和右侧
  2. 禁用在情节提要中滚动

这样做允许自动布局启动,并根据其内容动态调整textView的大小。


1
干净整洁!!感谢+1
Yogesh Patel

12

其次是DeyaEldeen的答案。
就我而言。我通过添加自动增加textview的高度

迅捷3

textView.translatesAutoresizingMaskIntoConstraints = false textView.isScrollEnabled = false


就我而言,使用textView.scrollEnabled = false; 它奏效了
乔纳森·加西亚

9

如果您textView被允许与内容一样高,那么

textView.isScrollEnabled = false

应该可以与自动布局一起使用。

如果您想要保持textView滚动状态,则需要添加可选的高度限制,

internal lazy var textViewHeightConstraint: NSLayoutConstraint = {
  let constraint = self.textView.heightAnchor.constraint(equalToConstant: 0)
  constraint.priority = .defaultHigh
  return constraint
}()

public override func layoutSubviews() {
  super.layoutSubviews()

  // Assuming there is width constraint setup on the textView.
  let targetSize = CGSize(width: textView.frame.width, height: CGFloat(MAXFLOAT))
  textViewHeightConstraint.constant = textView.sizeThatFits(targetSize).height
}

覆盖的原因layoutSubviews()是确保textView正确地水平放置,以便我们可以依靠宽度来计算高度。

由于高度限制设置为较低的优先级,因此如果垂直限制空间textView不足,则的实际高度将小于contentSize。并且textView将是可滚动的。


8

只需与您的textView的高度约束建立联系

@IBOutlet var textView: UITextView!
@IBOutlet var textViewHeightConstraint: NSLayoutConstraint!

并在下面使用此代码

textViewHeightConstraint.constant = self.textView.contentSize.height

类型“的UITextField”的值没有任何部件“contentSize”
阿南塔普拉萨德

@AnantaPrasad其UITextView而不是UItextField检查上面的连接
Shukla

8

Swift 5,使用扩展名:

extension UITextView {
    func adjustUITextViewHeight() {
        self.translatesAutoresizingMaskIntoConstraints = true
        self.sizeToFit()
        self.isScrollEnabled = false
    }
}

用例:

textView.adjustUITextViewHeight()

并且不必关心故事板上的texeView的高度(只需首先使用一个常数)


5

这个答案可能晚了,但我希望它能对某人有所帮助。

对我来说,这两行代码有效:

textView.isScrollEnabled = false
textView.sizeToFit()

但不要为您的Textview设置高度限制


1
并且不要将textView放在StackView中,所以我没有设法使其工作
djdance

4

我添加了这两行代码,对我来说很好用。

func adjustUITextViewHeight(textView : UITextView)
{
     textView.translatesAutoresizingMaskIntoConstraints = true
     textView.scrollEnabled = false
     textView.sizeToFit()
}

简单,无需图书馆
Lena Bru

3

以编程方式直接进行。只需按照以下步骤

  1. 将观察者添加到文本字段的内容长度

    [yourTextViewObject addObserver:self forKeyPath:@"contentSize" options:(NSKeyValueObservingOptionNew) context:NULL];
    
  2. 实施观察员

    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    UITextView *tv = object;
    
        //Center vertical alignment
        CGFloat topCorrect = ([tv bounds].size.height - [tv contentSize].height * [tv zoomScale])/2.0;
        topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
        tv.contentOffset = (CGPoint){.x = 0, .y = -topCorrect};
    
    
        mTextViewHeightConstraint.constant = tv.contentSize.height;
    
        [UIView animateWithDuration:0.2 animations:^{
    
            [self.view layoutIfNeeded];
        }];
    
    }
    
  3. 如果要在键入过程中过一段时间后停止textviewHeight增加,请实施此操作并将textview委托设置为self。

    -(BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text
    {
        if(range.length + range.location > textView.text.length)
        {
            return NO;
        }
    
        NSUInteger newLength = [textView.text length] + [text length] - range.length;
    
        return (newLength > 100) ? NO : YES;
    
    }
    

这是obj-c,我用的是swift。
DeyaEldeen '16

@DeyaEldeen oops,请编写相应的代码.. :)
Shaik Riyaz

我在问题中添加了swift标签,所以这一切都与swift有关。
DeyaEldeen '16

3

更好而又迅速的4添加为扩展:

extension UITextView {
    func resizeForHeight(){
        self.translatesAutoresizingMaskIntoConstraints = true
        self.sizeToFit()
        self.isScrollEnabled = false
    }
}

3

SWIFT 4

键入时更改大小

UITextViewDelegate

func textViewDidChange(_ textView: UITextView) {
        yourTextView.translatesAutoresizingMaskIntoConstraints = true
        yourTextView.sizeToFit()
        yourTextView.isScrollEnabled = false

        let calHeight = yourTextView.frame.size.height
        yourTextView.frame = CGRect(x: 16, y: 193, width: self.view.frame.size.width - 32, height: calHeight)
    }

加载时更改大小

func textViewNotasChange(arg : UITextView) {
        arg.translatesAutoresizingMaskIntoConstraints = true
        arg.sizeToFit()
        arg.isScrollEnabled = false

        let calHeight = arg.frame.size.height
        arg.frame = CGRect(x: 16, y: 40, width: self.view.frame.size.width - 32, height: calHeight)
    }

像这样调用第二个选项的函数:

textViewNotasChange(arg: yourTextView)

3

迅捷4+

使用自动布局非常简单!我将解释最简单的用例。比方说,只存在UITextView于你的UITableViewCell

  • 适合textViewcontentView有约束。
  • 禁用滚动textView
  • 更新tableView中的textViewDidChange

(您可以通过两种方式执行最后一步-将tableView实例传递到单元格,或者将textView委托设置为视图控制器,然后在其中实现textViewDidChange委托并更新表视图。)

就这样!

class TextViewCell: UITableViewCell {

    //MARK: UI Element(s)
    /// Reference of the parent table view so that it can be updated
    var tableView: UITableView!

    lazy var textView: UITextView = {
        let textView = UITextView()
        textView.isScrollEnabled = false
        // Other textView properties
        return textView
    }()

    //MARK: Padding Variable(s)
    let padding: CGFloat = 50

    //MARK: Initializer(s)
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        addSubviews()
        addConstraints()

        textView.becomeFirstResponder()
    }

    //MARK: Helper Method(s)
    func addSubviews() {
        contentView.addSubview(textView)
    }

    func addConstraints() {
        textView.leadingAnchor  .constraint(equalTo: contentView.leadingAnchor, constant: padding).isActive = true
        textView.trailingAnchor .constraint(equalTo: contentView.trailingAnchor, constant: -padding).isActive = true
        textView.topAnchor      .constraint(equalTo: contentView.topAnchor, constant: padding).isActive = true
        textView.bottomAnchor   .constraint(equalTo: contentView.bottomAnchor, constant: -padding).isActive = true
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

}

extension TextViewCell: UITextViewDelegate {

    func textViewDidChange(_ textView: UITextView) {
        self.tableView.beginUpdates()
        self.tableView.endUpdates()
    }

}

查看我的回购以获取完整的实现。


2

它的工作

func textViewDidChange(_ textView: UITextView) {
    let fixedWidth = textviewconclusion.frame.size.width
    textviewconclusion.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    let newSize = textviewconclusion.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    var newFrame = textviewconclusion.frame
    newFrame.size = CGSize(width: max(newSize.width, fixedWidth), height: newSize.height)
    textviewconclusion.frame = newFrame
}

2

在我的项目中,视图控制器涉及许多Constraints和StackView,并且我将TextView的高度设置为约束,并且它根据textView.contentSize.height值而变化。

步骤1:获得IB出口

@IBOutlet weak var textViewHeight: NSLayoutConstraint!

第二步:使用下面的委托方法。

extension NewPostViewController: UITextViewDelegate {
     func textViewDidChange(_ textView: UITextView) {
          textViewHeight.constant = self.textView.contentSize.height + 10
     }
}

1

1将观察者添加到文本字段的内容长度

   yourTextView.addObserver(self, forKeyPath: "contentSize", options: (NSKeyValueObservingOptions.new), context: nil);

2实施观察员

override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        let tv = object as! UITextView;
        var topCorrect = (tv.bounds.size.height - tv.contentSize.height * tv.zoomScale)/2.0;
        topCorrect = ( topCorrect < 0.0 ? 0.0 : topCorrect );
        tv.contentOffset.x = 0;
        tv.contentOffset.y = -topCorrect;
        self.yourTextView.contentSize.height = tv.contentSize.height;
        UIView.animate(withDuration: 0.2, animations: {
            self.view.layoutIfNeeded();
        });
    }

1

每当您需要根据内部内容大小调整textview的大小时,例如在消息应用程序中。使用cocoapods(GrowingTextView),比您自己编码动态调整textview的大小将使您的生活更轻松。


0

这是iOS 8.3附带的两个陷阱 textView.textContainer.maximumNumberOfLines = 10

请参考我的要旨

textView.attributedText = originalContent

let lineLimit = 10
textView.isEditable = true
textView.isScrollEnabled = false
textView.textContainerInset = .zero // default is (8, 0, 8, 0)
textView.textContainer.maximumNumberOfLines = lineLimit // Important condition
textView.textContainer.lineBreakMode = .byTruncatingTail

// two incomplete methods, which do NOT work in iOS 8.3

// size.width可能比maxSize.width小 ————遗憾的是 iOS 8.3 上此方法无视maximumNumberOfLines参数,所以得借助于UILabel
// size.width may be less than maxSize.width, ---- Do NOT work in iOS 8.3, which disregards textView.textContainer.maximumNumberOfLines
// let size = textView.sizeThatFits(maxSize) 

// 遗憾的是 iOS 8.3 上此方法失效了,得借助于UILabel
// Does not work in iOS 8.3
// let size = textView.layoutManager.usedRectForTextContainer(textView.textContainer).size 

// Suggested method: use a temperary label to get its size
let label = UILabel(); label.attributedText = originalContent
let size = label.textRect(forBounds: CGRect(origin: .zero, size: maxSize), limitedToNumberOfLines: lineLimit).size
textView.frame.size = size

0

在此声明

    fileprivate weak var textView: UITextView!

在此处致电您的setupview

    override func viewDidLoad() {
        super.viewDidLoad()

         setupViews()
    }

在这里设置

    fileprivate func setupViews() {

    let textView = UITextView()
    textView.translatesAutoresizingMaskIntoConstraints = false
    textView.text = "your text here"
    textView.font = UIFont.poppinsMedium(size: 14)
    textView.textColor = UIColor.brownishGrey
    textView.textAlignment = .left
    textView.isEditable = false
    textView.isScrollEnabled = false
    textView.textContainerInset = UIEdgeInsets(top: 20, left: 20, bottom: 20, right: 20)

   self.view.addSubview(textView)

   self.textView = textView

   setupConstraints()

   }

在这里设置约束

   fileprivate func setupConstraints() {

    NSLayoutConstraint.activate([

        textView.topAnchor.constraint(equalTo: view.topAnchor, constant: 20),
        textView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20),
        textView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -20),
        textView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -20),
        textView.heightAnchor.constraint(greaterThanOrEqualToConstant: 150),
        ])
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.