包含堆栈视图

时间:2017-07-18 18:52:40

标签: uiscrollview uikit uistackview

我的目标是创建一个堆栈视图,它可以容纳任意(~5-10)排列的子视图,并且如果它的高度变得比其包含的视图高,则变为可滚动。为此,我使用滚动视图。

我的理解是,如果每个排列的子视图都有明确的高度约束,那么distribution设置为fill的堆栈视图应具有内在内容大小。所以我可以将堆栈视图添加到滚动视图中,滚动可以从堆栈视图的内在内容大小中获取其内容大小。

我也试图让这个滚动堆栈视图对帧中的变化(来自键盘)具有鲁棒性。

我花了很多时间阅读很多关于Scroll View和StackView以及所有编程指南的长篇文章但却无法让它完美地运作。

以下代码及其略有变化的内容始终为content size is ambiguousHeight is ambiguous for Scroll View。当键盘弹出时(点击堆栈视图中的文本视图)我只是从Scroll View的底部约束常量中减去400。我的想法是Scroll View的框架/边界将变得小于Stack View的内在内容高度,并且会发生滚动。但是,屏幕只是空白。控制台中没有约束记录。

我花了很多时间思考这个场景中的所有考虑因素,但它似乎超出了我的范围。我非常感谢任何有关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 个答案:

答案 0 :(得分:0)

我在这里添加我的工作示例:

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
    }
}