textViewDidChange изменяется только при вводе полной строки.Я хочу, чтобы проверить каждый персонаж - PullRequest
0 голосов
/ 30 января 2019

У меня есть 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 голосов
/ 30 января 2019

Я реализовал это, используя ограничения в раскадровке.

Раскадровка выглядит следующим образом: 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, динамически использующего здесь ограничения, и он увеличивается, если вы добавите текст за его рамки.

Надеюсь, это поможет достичь того, что вы хотите.

0 голосов
/ 30 января 2019

Вам нужно использовать 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
        }
    }
}

0 голосов
/ 30 января 2019

textViewDidChange(...) фактически должен реагировать на каждый введенный символ (через клавиатуру, а не программно).Возможно, что textView.sizeThatFits(...) не вернет то, что вы хотите.Быстрый просмотр документации не показывает переопределения реализации UIView, которая просто возвращает тот же размер представления.

NSAttributedString boundingRect (с: options: context:) , возможно, стоит изучить, чтобы получить желаемый размер текста (и, следовательно, представления).

Также обратите внимание на мой комментарий к вашему вопросу.Если для scrollEnabled установлено значение false, внутренний текстовый вид уже должен быть равен нужному размеру, и вам даже не нужно устанавливать ограничение по высоте.Если ваш 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()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...