Scrollview中的两个动态Stack View

Posted

技术标签:

【中文标题】Scrollview中的两个动态Stack View【英文标题】:Two dynamic Stackviews in Scrollview 【发布时间】:2018-09-15 23:38:01 【问题描述】:

这是我的视图层次结构

ScrollView
 -> View
    -> Stackview1
       -> view1
       -> view2
       .
       .
       .
    -> Stackview1
       -> view1
       -> view2
       .
       .
       .

所以这里我的 stackview 的高度是根据 .swift 文件中添加的视图动态生成的

如果我给超级视图提供底部约束,它只适用于单个堆栈视图,但如果我同时使用两个堆栈视图,则不会考虑第二个堆栈视图。

【问题讨论】:

如何为每个堆栈视图添加容器视图? 但是我的容器视图高度不能根据 stackview 增加 考虑在超级堆栈视图中添加两个堆栈视图。 ScrollView 包含包含两个堆栈视图的堆栈视图。 【参考方案1】:

很难说问题出在哪里,因为您还没有发布您的限制条件,但解决方案非常简单:

您需要以下约束:

滚动视图:

topAnchorview.topAnchor leadingAnchorview.leadingAnchor trailingAnchorview.trailingAnchor bottomAnchorview.bottomAnchor

包装了 2 个 UIStackView 的 UIView:

topAnchorscrollView.topAnchor leadingAnchorscrollView.leadingAnchor trailingAnchorscrollView.trailingAnchor bottomAnchorscrollView.bottomAnchor

上层 StackView:

topAnchorwrapperView.topAnchor leadingAnchorwrapperView.leadingAnchor trailingAnchorwrapperView.trailingAnchor widthAnchor to scrollView.widthAnchor(定义ScrollView的contentSize的宽度)

较低的 StackView:

topAnchorupperStackView.bottomAnchor leadingAnchorwrapperView.leadingAnchor trailingAnchorwrapperView.trailingAnchor bottomAnchorwrapperView.bottomAnchor

现在,当您将UIView 添加到UIStackViews 之一时,UIScrollView 会自动更新。

这是一个工作示例:(我添加了两个 UIButtons 以向两个 UIStackViews 添加更多 UIViews

class ViewController: UIViewController 

    let upperStackView = UIStackView()
    let lowerStackView = UIStackView()

    override func viewDidLoad() 
        super.viewDidLoad()

        let scrollView = UIScrollView()
        view.addSubview(scrollView)
        scrollView.backgroundColor = .white
        scrollView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            scrollView.topAnchor.constraint(equalTo: view.topAnchor),
            scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
            scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
            scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
        ])

        let wrapperView = UIView()
        scrollView.addSubview(wrapperView)
        wrapperView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            wrapperView.topAnchor.constraint(equalTo: scrollView.topAnchor),
            wrapperView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
            wrapperView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
            wrapperView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
        ])

        upperStackView.axis = .vertical
        upperStackView.distribution = .equalSpacing
        upperStackView.alignment = .fill
        wrapperView.addSubview(upperStackView)
        upperStackView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            upperStackView.topAnchor.constraint(equalTo: wrapperView.topAnchor),
            upperStackView.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor),
            upperStackView.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor),
            upperStackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
            ])

        lowerStackView.axis = .vertical
        lowerStackView.distribution = .equalSpacing
        lowerStackView.alignment = .fill
        wrapperView.addSubview(lowerStackView)
        lowerStackView.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([
            lowerStackView.topAnchor.constraint(equalTo: upperStackView.bottomAnchor),
            lowerStackView.leadingAnchor.constraint(equalTo: wrapperView.leadingAnchor),
            lowerStackView.trailingAnchor.constraint(equalTo: wrapperView.trailingAnchor),
            lowerStackView.bottomAnchor.constraint(equalTo: wrapperView.bottomAnchor)
            ])

        for _ in 0...3 
            addView(to: upperStackView)
            addView(to: lowerStackView)
        

        let lowerButton = UIButton(type: .system)
        lowerButton.setTitle("Add to lower StackView", for: .normal)
        lowerButton.backgroundColor = .white
        lowerButton.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(lowerButton)
        NSLayoutConstraint.activate([
            lowerButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -60),
            lowerButton.widthAnchor.constraint(equalToConstant: 240),
            lowerButton.heightAnchor.constraint(equalToConstant: 44),
            lowerButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
        ])
        lowerButton.addTarget(self, action: #selector(addViewToLowerStackView), for: .touchUpInside)

        let upperButton = UIButton(type: .system)
        upperButton.setTitle("Add to upper StackView", for: .normal)
        upperButton.backgroundColor = .white
        upperButton.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(upperButton)
        NSLayoutConstraint.activate([
            upperButton.bottomAnchor.constraint(equalTo: lowerButton.topAnchor, constant: -20),
            upperButton.widthAnchor.constraint(equalToConstant: 240),
            upperButton.heightAnchor.constraint(equalToConstant: 44),
            upperButton.centerXAnchor.constraint(equalTo: view.centerXAnchor)
            ])
        upperButton.addTarget(self, action: #selector(addViewToUpperStackView), for: .touchUpInside)
    

    func addView(to stackView: UIStackView) 
        let view = UIView()
        view.backgroundColor = stackView == upperStackView ? .blue : .green
        view.alpha = CGFloat(stackView.arrangedSubviews.count + 1) * 0.1
        view.translatesAutoresizingMaskIntoConstraints = false
        NSLayoutConstraint.activate([view.heightAnchor.constraint(equalToConstant: 120)])
        stackView.addArrangedSubview(view)
    

    @objc func addViewToUpperStackView() 
        addView(to: upperStackView)
    

    @objc func addViewToLowerStackView() 
        addView(to: lowerStackView)
    

更新:

您也可以仅使用情节提要完成这项工作:

【讨论】:

感谢您的回答,我添加了视图,因为我的视图中有一些其他标签 变化不大。我更新了我的答案以包括UIView @再次感谢 joerm。所以我的问题是我需要两者都做吗?代码和通过故事板?因为我是从 stroyboard 设置的,所以它会导致我的 y 位置或滚动视图高度发生冲突错误 我的例子只是代码。不涉及情节提要。查看我更新的答案以获取仅使用情节提要的示例。 @PJR "conflicts error for y position or height of scrollview" 可以通过向堆栈视图添加一个或多个固定高度项(或设置最小高度约束)来解决

以上是关于Scrollview中的两个动态Stack View的主要内容,如果未能解决你的问题,请参考以下文章

SwiftUI - ScrollView 没有一直滚动到底部

如何在 SwiftUI 中设置 ScrollView 的 contentInset

ScrollView中的UILabel sizeToFit

动态 UIScrollView 中的动态 UITextView - iOS

android中的scrollView问题

无法在具有动态宽度的 Tablecell 中并排自动布局两个 UILabel