仅在键入完整字符串时,textViewDidChange才会更改。我要它检查每个字符

时间:2019-01-30 17:00:32

标签: ios swift uitextview

我有一个UITextView,当键入超出其框架范围的文本时,其高度会动态变化。但是,仅当键入完整的字符串并按空格键时,高度才会改变。这留下了一个尴尬的时刻,使用户看不到他们正在键入的单词。

如何让我的textViewDidChange对键入的每个字符而不是输入完整的字符串做出反应?

这是初始化变量:

lazy var descriptionTextView: UITextView = {
    let tv = UITextView()
    tv.backgroundColor = .white
    tv.font = UIFont.systemFont(ofSize: 18)
    tv.frame = CGRect(x: 0, y: 0, width: 200, height: 40)
    tv.translatesAutoresizingMaskIntoConstraints = false
    tv.delegate = self
    tv.isScrollEnabled = false
    return tv
}()

然后将其添加到子视图中,并将其锚定在我的viewDidLoad中:

view.addSubview(descriptionTextView)

descriptionTextView.anchor(top: privacyLabel.bottomAnchor, left: 
view.leftAnchor, bottom: descriptionTextViewUnderLine.topAnchor, right: view.rightAnchor, paddingTop: 16, paddingLeft: 24, paddingBottom: 0, paddingRight: 24, width: 0, height: 40)

在扩展名中,我输入了textViewDidChange

func textViewDidChange(_ textView: UITextView) {
    let size = CGSize(width: view.frame.width, height: .infinity)
    let estimatedSize = textView.sizeThatFits(size)
    textView.constraints.forEach { (constraint) in
        if constraint.firstAttribute == .height {
            constraint.constant = estimatedSize.height
        }
    }
}

在此先感谢您的帮助!

3 个答案:

答案 0 :(得分:0)

textViewDidChange(...)实际上应该对输入的每个字符做出反应(通过键盘,而不是通过编程)。 textView.sizeThatFits(...)可能没有返回您想要的内容。快速浏览文档并不会发现对UIView实现的替代,它仅返回与视图相同的大小。

NSAttributedString的boundingRect(with:options:context:)可能值得研究以获取所需的文本大小(以及视图的大小)。

也请注意我对您的问题的评论。将scrollEnabled设置为false应该已经将textView的固有大小设置为所需的大小,并且甚至不必设置高度限制。如果您的textView被挤压在具有相同优先级约束的视图之间,则可以沿垂直轴升高compressionResistancePriority

一个简短的代码片段来说明示例(不是您的问题的答案,但可能是您尝试做的事情的另一种方法):

//: A UIKit based Playground for presenting user interface

import UIKit
import PlaygroundSupport

class MyViewController : UIViewController, UITextViewDelegate {
    private lazy var textView = UITextView()
    override func loadView() {
        let view = UIView()
        view.backgroundColor = .orange


        textView.frame = view.bounds
        textView.backgroundColor = .white
        textView.isScrollEnabled = false
        textView.translatesAutoresizingMaskIntoConstraints = false

        view.addSubview(textView)
        NSLayoutConstraint.activate(
            [textView.topAnchor.constraint(equalTo: view.topAnchor),
            textView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            textView.leadingAnchor.constraint(equalTo: view.leadingAnchor)]
        )

        textView.delegate = self
        self.view = view
    }

    func textViewDidChange(_ textView: UITextView) {
        print(textView.text)
    }
}
// Present the view controller in the Live View window
PlaygroundPage.current.liveView = MyViewController()

答案 1 :(得分:0)

我已经使用情节提要中的约束实现了这一点。

情节提要如下: enter image description here

我在Controller中添加的代码是:

class ViewController: UIViewController {

    @IBOutlet weak var messageTextView: UITextView!

    @IBOutlet weak var messageTextViewHeightConstraint: NSLayoutConstraint!
}

extension ViewController: UITextViewDelegate {

    public func textViewDidChange(_ textView: UITextView) {
        resizeTextView(textView: textView)
    }

    func resizeTextView(textView: UITextView) {
        let sizeThatFitsTextView = messageTextView.sizeThatFits(CGSize(width: messageTextView.frame.width, height: CGFloat(MAXFLOAT)))

        messageTextViewHeightConstraint.constant = sizeThatFitsTextView.height
    }

}

我在这里使用约束条件来动态更改UITextView的高度,如果您要添加超出其范围的文本,则会增加它的高度。

希望这有助于实现您想要的。

答案 2 :(得分:0)

您需要使用UITextView框架而不是UIView

func textViewDidChange(_ textView: UITextView) {
    let size = CGSize(width: textView.frame.width, height: .infinity)
    let estimatedSize = textView.sizeThatFits(size)
    textView.constraints.forEach { (constraint) in
        if constraint.firstAttribute == .height {
            constraint.constant = estimatedSize.height
        }
    }
}