Вид / размер прокрутки всегда неоднозначны, когда содержат вид стека

Моя цель - создать Stack View, который может содержать произвольные (~5-10) упорядоченные подпредставления и стать прокручиваемым, если его высота станет выше, чем представление, содержащееся в нем. Для этого я использую представление прокрутки.

Я понимаю, что Stack View которого distribution установлен в fill должен иметь внутренний размер контента, если каждое упорядоченное подпредставление имеет явное ограничение по высоте. Таким образом, я могу добавить представление стека к представлению прокрутки, и прокрутка может получить размер своего содержимого из собственного размера содержимого представления стека.

Я также пытаюсь сделать просмотр стека прокрутки устойчивым к изменениям в кадре (с клавиатуры).

Я потратил много времени и прочитал много длинных статей о Scroll View и StackView и всех руководствах по программированию, но не могу заставить его работать идеально.

Следующий код и небольшие изменения в нем всегда дают content size is ambiguous или же Height is ambiguous for Scroll View, Когда клавиатура всплывает (от нажатия на текстовое представление в представлении стека), я просто вычитаю 400 из константы нижнего ограничения представления прокрутки. Я думаю, что рамка / границы представления прокрутки станут меньше, чем внутренняя высота содержимого представления стека, и произойдет прокрутка. Однако экран просто гаснет. В консоли также нет журналов ограничений.

Я потратил очень много времени на обдумывание всех соображений в этом сценарии, но он кажется мне просто не по силам. Я был бы очень признателен за любую помощь или указатели по теме Stack View в Scroll Views.

Вот мой текущий эксперимент с ним:

class ViewController: UIViewController {

    let scrollView = UIScrollView()
    var scrollViewBottomConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()

        // stack view setup (one blue and hellow view at 100 height)
        let stackView = UIStackView()
        stackView.distribution = .fill
        stackView.axis = .vertical
        let v1 = UIView()
        v1.backgroundColor = .blue
        let v2 = UITextView()
        v2.backgroundColor = .yellow
        stackView.addArrangedSubview(v1)
        stackView.addArrangedSubview(v2)


        // scroll
        scrollView.addSubview(stackView)

        view.addSubview(scrollView)

        // constraints for stack view arranged views
        v1.heightAnchor.constraint(equalToConstant: 100).isActive = true
        v2.heightAnchor.constraint(equalToConstant: 100).isActive = true

        // pin scroll view in main view
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        // pin scroll view to stack view's bottom anchor
        scrollViewBottomConstraint = scrollView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0)
        scrollViewBottomConstraint.isActive = true


        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
        stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true
        stackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true


        // constrain "content view to main view and not scroll view."
        stackView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1).isActive = true


        NotificationCenter.default.addObserver(self,
                                               selector: #selector(ViewController.handleKeyboard),
                                               name: Notification.Name.UIKeyboardWillShow,
                                               object: nil)
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(ViewController.handleKeyboard),
                                               name: Notification.Name.UIKeyboardWillHide,
                                               object: nil)


    }

    func handleKeyboard(notification: Notification) {

        scrollViewBottomConstraint.constant = -400
    }
}

1 ответ

Я добавляю сюда мой рабочий пример:

class ViewController: UIViewController {

    let scrollView = UIScrollView()
    var scrollViewBottomConstraint: NSLayoutConstraint!

    override func viewDidLoad() {
        super.viewDidLoad()

        // stack view setup (one blue and hellow view at 100 height)
        let stackView = UIStackView()
        stackView.distribution = .fill
        stackView.axis = .vertical
        let v1 = UIView()
        v1.backgroundColor = .blue
        let v2 = UITextView()
        v2.backgroundColor = .yellow
        let v3 = UITextView()
        v3.backgroundColor = .green
        let v4 = UITextView()
        v4.backgroundColor = .brown
        stackView.addArrangedSubview(v1)
        stackView.addArrangedSubview(v2)
        stackView.addArrangedSubview(v3)
        stackView.addArrangedSubview(v4)


        // scroll
        scrollView.addSubview(stackView)

        view.addSubview(scrollView)

        // constraints for stack view arranged views
        v1.heightAnchor.constraint(equalToConstant: 200).isActive = true
        v2.heightAnchor.constraint(equalToConstant: 200).isActive = true
        v3.heightAnchor.constraint(equalToConstant: 180).isActive = true
        v4.heightAnchor.constraint(equalToConstant: 250).isActive = true

        // pin scroll view in main view
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
        scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
        scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
        scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 100).isActive = true
        // pin scroll view to stack view's bottom anchor
        scrollViewBottomConstraint = scrollView.bottomAnchor.constraint(equalTo: stackView.bottomAnchor, constant: 0)
        scrollViewBottomConstraint.isActive = true


        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.leftAnchor.constraint(equalTo: scrollView.leftAnchor, constant: 0).isActive = true
        stackView.rightAnchor.constraint(equalTo: scrollView.rightAnchor, constant: 0).isActive = true
        stackView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0).isActive = true


        // constrain "content view to main view and not scroll view."
        stackView.widthAnchor.constraint(equalTo: view.widthAnchor, multiplier: 1).isActive = true


        NotificationCenter.default.addObserver(self,
                                               selector: #selector(ViewController.handleKeyboard),
                                               name: Notification.Name.UIKeyboardWillShow,
                                               object: nil)
        NotificationCenter.default.addObserver(self,
                                               selector: #selector(ViewController.handleKeyboard),
                                               name: Notification.Name.UIKeyboardWillHide,
                                               object: nil)


    }

    func handleKeyboard(notification: Notification) {

        scrollViewBottomConstraint.constant = -400
    }
}
Другие вопросы по тегам