Обновление автоматического макета после изменения размера кадра объекта - PullRequest
0 голосов
/ 27 сентября 2018

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

enter image description here

После загрузки представления я беру некоторые текстовые данные изаполнить UITextView.Элемент «Обо мне» может состоять из нескольких строк, поэтому я изменяю размер этого конкретного кадра.Затем я получаю следующее.

enter image description here

Вы видите, как текстовое представление обо мне охватывает следующее поле?Как я могу изменить размер автоматического макета с новым размером текста?Я искал и нашел несколько предложений по использованию setNeedsLayout и layoutIfNeeded, но ни одно не помогло.

Я настраиваю автоматический макет следующим образом:

    inputsContainerView.addSubview(ageInput)
    ageInput.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
    ageInput.topAnchor.constraint(equalTo: inputsContainerView.topAnchor, constant: 10).isActive = true
    ageInput.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
    ageInput.heightAnchor.constraint(equalToConstant: 60).isActive = true

    inputsContainerView.addSubview(genderInput)
    genderInput.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
    genderInput.topAnchor.constraint(equalTo: ageInput.bottomAnchor).isActive = true
    genderInput.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
    genderInput.heightAnchor.constraint(equalToConstant: 60).isActive = true

    inputsContainerView.addSubview(aboutInput)
    aboutInput.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
    aboutInput.topAnchor.constraint(equalTo: genderInput.bottomAnchor).isActive = true
    aboutInput.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
    aboutInput.heightAnchor.constraint(equalToConstant: 60).isActive = true

    inputsContainerView.addSubview(memberSinceInput)
    memberSinceInput.leftAnchor.constraint(equalTo: inputsContainerView.leftAnchor).isActive = true
    memberSinceInput.topAnchor.constraint(equalTo: aboutInput.bottomAnchor).isActive = true
    memberSinceInput.widthAnchor.constraint(equalTo: inputsContainerView.widthAnchor).isActive = true
    memberSinceInput.heightAnchor.constraint(equalToConstant: 60).isActive = true

После загрузки представления я получаю данныеи измените размер рамки текстового представления обо мне, используя следующую функцию:

func resizeTextView(_ 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
}

1 Ответ

0 голосов
/ 27 сентября 2018

На вашем месте я бы использовал UITableView для создания этой формы и добавления метки и UITextView внутри ячеек.

Вы можете сделать UITableViewCell, как показано ниже, где я установил высотуметка до 60 и автоматическая разметка.UITextView также использует автоматическое расположение и подгонку нижней части ячейки.

import UIKit

class UserDetailCell: UITableViewCell {

    var userDetailLabel : UILabel = {
        var label = UILabel()
        label.numberOfLines = 0
        label.translatesAutoresizingMaskIntoConstraints = false
        label.textColor = UIColor.lightGray
        return label
    }()

    var userDetailTextView : UITextView = {
        var tv = UITextView()
        tv.translatesAutoresizingMaskIntoConstraints = false
        tv.isScrollEnabled = false
        return tv
    }()

    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)

        setupUI()
    }

    func setupUI(){
        addSubview(userDetailLabel)

        NSLayoutConstraint.activate([
                userDetailLabel.topAnchor.constraint(equalTo: topAnchor),
                userDetailLabel.leftAnchor.constraint(equalTo: leftAnchor, constant: 8),
                userDetailLabel.rightAnchor.constraint(equalTo: rightAnchor),
                userDetailLabel.heightAnchor.constraint(equalToConstant: 60)
            ])

        addSubview(userDetailTextView)
        NSLayoutConstraint.activate([
            userDetailTextView.topAnchor.constraint(equalTo: userDetailLabel.bottomAnchor),
            userDetailTextView.leftAnchor.constraint(equalTo: leftAnchor, constant: 8),
            userDetailTextView.rightAnchor.constraint(equalTo: rightAnchor),
            userDetailTextView.bottomAnchor.constraint(equalTo: bottomAnchor)
            ])
    }

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

}

Тогда ваш UIViewController должен быть таким, как показано ниже.Я устанавливаю делегата для UITextView в методе cellForRowAt indexPath.Поскольку я установил делегат, будет вызван метод делегата textViewDidChange.Это написано внутри расширения.

import UIKit

class UserDetailsController: UITableViewController {

    let cellId = "cell"
    var person = Person(myAge: 20, myGender: "Male", aboutMe: "Hello my name is jake waisee. What is your name? goayngeHello my name is jake waisee. What is your name? goayngeHello my name is jake waisee. What is your name? goayngeHello my name is jake waisee. What is your name? goaynge")

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.register(UserDetailCell.self, forCellReuseIdentifier: cellId)
        tableView.rowHeight = UITableView.automaticDimension
        tableView.estimatedRowHeight = 100
    }

    // MARK: - Table view data source

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return 3
    }


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath) as! UserDetailCell
        cell.userDetailTextView.delegate = self
        cell.userDetailTextView.tag = indexPath.row
        if indexPath.row == 0{
            cell.userDetailLabel.text = "Age"
            cell.userDetailTextView.text = "\(person.age)"
        }else if indexPath.row == 1{
            cell.userDetailLabel.text = "Gender"
            cell.userDetailTextView.text = person.gender
        }else if indexPath.row == 2{
            cell.userDetailLabel.text = "About me"
            cell.userDetailTextView.text = person.aboutMe
        }

        return cell
    }

}


extension UserDetailsController: UITextViewDelegate {
    func textViewDidChange(_ textView: UITextView) {
        print(textView.text)
        if textView.tag == 2 {
            person.aboutMe = textView.text
        }else if textView.tag == 0 {
            person.age = Int(textView.text) ?? 0
        }else if textView.tag == 1 {
            person.gender = textView.text
        }

        //this will keep the textview growing as we type
        tableView.beginUpdates()
        tableView.endUpdates()
    }
}

Надеюсь, это поможет вам.Ваш интерфейс должен выглядеть примерно так:enter image description here

...