如何动态地将TextView高度更改为阈值,然后允许滚动?

时间:2016-07-16 21:34:21

标签: ios swift scroll uitextview

我有一个TextView,其最小高度为33.从故事板中禁用滚动。 TextView应根据内容增加高度,直到达到100的最大高度。然后我将scrollEnabled更改为true,将TextView的高度更改为最大高度100,但高度更改为33.如何修复这个问题?

import UIKit

class ViewController: UIViewController, UITextViewDelegate {

@IBOutlet weak var messageTextView: UITextView!
let messageTextViewMaxHeight: CGFloat = 100

override func viewDidLoad() {
    super.viewDidLoad()
    self.messageTextView.delegate = self
}

func textViewDidChange(textView: UITextView) {

    if textView.frame.size.height >= self.messageTextViewMaxHeight {
        textView.scrollEnabled = true
        textView.frame.size.height = self.messageTextViewMaxHeight
    } else {
        textView.scrollEnabled = false
    }
}
}

enter image description here

7 个答案:

答案 0 :(得分:6)

您的代码似乎需要进行两项更改,并且可以正常运行。

  1. 取代最小约束高度,而不是最大高度为100:
  2. Height Constraint for TextView

    1. 更改代码如下:

       import UIKit
      
      class ViewController: UIViewController, UITextViewDelegate
      {
          @IBOutlet weak var messageTextView: UITextView!
      
          let messageTextViewMaxHeight: CGFloat = 100
          override func viewDidLoad()
          {
              super.viewDidLoad()
              messageTextView.delegate = self
          }
      
          func textViewDidChange(textView: UITextView)
          {
              if textView.contentSize.height >= self.messageTextViewMaxHeight
              {
                  textView.scrollEnabled = true
              }
              else
                  {
                  textView.frame.size.height = textView.contentSize.height
                  textView.scrollEnabled = false // textView.isScrollEnabled = false for swift 4.0
              }
          }
      }
      

答案 1 :(得分:1)

这采用了相似的方法来处理已接受的答案,但要确保textView在两个高度状态下都完全受约束。

(接受的答案中有一个错误-在启用滚动功能时,使用具有<=关系的高度约束不足以完全约束textView,因为在这种情况下,视图不提供{{ 1}}。您可以在IB中(禁用滚动功能)或在运行时通过视图调试看到它。)

这是必需的:

intrinsicContentSize

无需手动设置框架,因为在这两种情况下都可以使用自动布局。

答案 2 :(得分:0)

解决问题的简单方法是在textViewDidChange调用时更改textView的框架。 UITextView实际上是一个UIScrollView。如果必须使用约束,则必须更改约束的常量。 这是我的代码:

import UIKit

let width = UIScreen.mainScreen().bounds.width

class ViewController: UIViewController, UITextViewDelegate {

    var messageTextView: UITextView!
    let messageTextViewMaxHeight: CGFloat = 100

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.redColor()
        messageTextView = UITextView(frame: CGRectMake(0, 200 - 33, width, 33))
        messageTextView.backgroundColor = UIColor.whiteColor()
        view.addSubview(messageTextView)
        self.messageTextView.delegate = self
    }

    //
    let bottomY: CGFloat = 200

    func textViewDidChange(textView: UITextView) {
        let formerRect = textView.frame

        if formerRect.height > messageTextViewMaxHeight{

        }
        else{
            textView.frame = CGRectMake(formerRect.origin.x, bottomY - textView.contentSize.height, width, textView.contentSize.height)
        }
    }
} 

答案 3 :(得分:0)

也许下面的代码更好一点。

import UIKit

let width = UIScreen.mainScreen().bounds.width

class ViewController: UIViewController, UITextViewDelegate {

    var messageTextView: UITextView!
    let messageTextViewMaxHeight: CGFloat = 100

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = UIColor.redColor()
        messageTextView = UITextView(frame: CGRectMake(0, 200 - 33, width, 33))
        messageTextView.backgroundColor = UIColor.whiteColor()
        view.addSubview(messageTextView)
        self.messageTextView.delegate = self
    }

    //
    let bottomY: CGFloat = 200

    func textView(textView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
        if text == "\n"{
            let formerRect = textView.frame
            let contentSize = textView.contentSize
            if contentSize.height < formerRect.height{
                //
            }
            else{
                if contentSize.height >= messageTextViewMaxHeight{
                    //
                }
                else{
                    textView.frame = CGRectMake(formerRect.origin.x, bottomY - contentSize.height, width, contentSize.height)
                }
            }
        }
        return true
    }

}

答案 4 :(得分:0)

在表格视图单元格中查看了很多小时的文本视图问题后,这个解决方案对我有用。我正在使用Masonry,但也可以在IB中创建约束。

请注意,textview委托是使用。这是有利的,因为无论是以编程方式还是通过用户输入更改文本都无关紧要。无论哪种方式,只要文本视图更改其内容,就会调用layoutSubviews。

如果您想直接在视图控制器中使用此功能,可以使用viewDidLayoutSubviews代替layoutSubviews

@implementation TextViewCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
    self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
    if (self){
        UITextView *textView = [[UITextView alloc] initWithFrame:CGRectZero];
        textView.scrollEnabled = NO;
        self.textView = textView;
        [self.contentView addSubview:self.textView];

        [self.textView mas_remakeConstraints:^(MASConstraintMaker *make) {
            make.leading.equalTo(self.contentView.mas_leadingMargin);
            make.trailing.equalTo(self.contentView.mas_trailingMargin);
            make.top.equalTo(self.contentView.mas_topMargin);
            make.bottom.equalTo(self.contentView.mas_bottomMargin);
            make.height.lessThanOrEqualTo(@100.0).with.priorityHigh();
            make.height.greaterThanOrEqualTo(@30.0).with.priorityHigh();
        }];
    }
    return self;
}


- (void)layoutSubviews{
    CGSize size = [self.textView sizeThatFits:CGSizeMake(self.textView.bounds.size.width, 10000)];
    self.textView.scrollEnabled = size.height > 100.0;
    [super layoutSubviews];
}

@end

答案 5 :(得分:0)

创建一个继承自UITextView的类,并将以下内容添加到该类中:

class CustomTextView: UITextView, UITextViewDelegate {

    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)

        delegate = self
    }

    var maxHeight: CGFloat = 200

    override var intrinsicContentSize: CGSize {
        var size = super.intrinsicContentSize
        if size.height > maxHeight {
            size.height = maxHeight
            isScrollEnabled = true
        } else {
            isScrollEnabled = false
        }
        return size
    }

    override var text: String! {
        didSet {
            invalidateIntrinsicContentSize()
        }
    }

    func textViewDidChange(_ textView: UITextView) {
        invalidateIntrinsicContentSize()
    }

}

注意: -创建CustomTextView之后,可以将maxHeight初始化为无穷大并设置maxHeight。此类可以在应用程序中需要的任何地方重复使用,并且可以针对不同的情况修改最大高度。

答案 6 :(得分:0)

我的解决方案是,在CostumeView上,我向UITextView添加了约束:

 textInput.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
  textInput.topAnchor.constraint(equalTo: divider.bottomAnchor, constant: 5),
  textInput.heightAnchor.constraint(lessThanOrEqualToConstant: 100), // very important
  textInput.leadingAnchor.constraint(equalTo: self.safeAreaLayoutGuide.leadingAnchor),
  textInput.bottomAnchor.constraint(equalTo: self.safeAreaLayoutGuide.bottomAnchor)])

“ textInput.heightAnchor.constraint(lessThanOrEqualToConstant:100)”就是它的窍门。 因此,我将UITextView设置为isScrollEnabled = false:

textView.isScrollEnabled = false

然后在ViewController上添加UITextViewDelegate:

extension InboxMsgVC: UITextViewDelegate {

最后我添加了以下方法:

func textViewDidChange(_ textView: UITextView) {
if textView.contentSize.height >= 100 {
  textView.isScrollEnabled = true
} else {
  textView.isScrollEnabled = false 
}

}

是的,它对我来说很好,Swift 5。