假设我在UIStackView中添加了更多可以显示的视图,我如何让UIStackView滚动?


当前回答

我给你一个正确的解决方案

对于 Xcode 11+

步骤1: 添加一个ScrollView并调整它的大小

步骤2: 为ScrollView添加约束

步骤3: 添加一个StackView到ScrollView,并调整它的大小。

步骤4: 为StackView添加约束(Stask View ->内容布局指南->“领先,顶部,后面,底部”)

步骤4.1: 正确的约束->常量(…->常量= 0)

步骤5: 为StackView添加约束(Stask View -> Frame Layout Guide -> "Equal width ")

步骤6示例: 添加两个带有HeightConstraints和RUN的UIView

希望对大家有用

其他回答

例如,垂直堆栈视图/滚动视图(使用EasyPeasy自动布局):

let scrollView = UIScrollView()
self.view.addSubview(scrollView)
scrollView <- [
    Edges(),
    Width().like(self.view)
]

let stackView = UIStackView(arrangedSubviews: yourSubviews)
stackView.axis = .vertical
stackView.distribution = .fill    
stackView.spacing = 10
scrollView.addSubview(stackView)
stackView <- [
    Edges(),
    Width().like(self.view)
]

只要确保每个子视图的高度都已定义!

正如Eik所说,UIStackView和UIScrollView很好地结合在一起。

关键是UIStackView处理不同内容的可变高度/宽度,然后UIScrollView做它的工作很好地滚动/反弹内容:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()
    scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height)       
}

将stackview中的动态元素嵌入到scrollview中的一种简单方法。在XIB中,在UIScrollView中添加一个UIStackView,并添加stackview适合scrollview的约束(top, bottom, lead, trail),并添加一个约束来匹配它们之间的水平中心。但是将最后一个约束标记为“在构建时移除”。它使XIB高兴,避免错误。

水平滚动示例:

然后:

然后在你的代码中,像这样在你的stackview中添加按钮这样的元素:

array.forEach { text in
     let button = ShadowButton(frame: .zero)
     button.setTitle(text, for: .normal)
     myStackView.addArrangedSubview(button)
     button.heightAnchor.constraint(equalToConstant: 40).isActive = true
     button.widthAnchor.constraint(equalToConstant: 80).isActive = true
}

水平滚动(UIScrollView中的UIStackView)

用于水平滚动。首先,创建一个UIStackView和一个UIScrollView,并按以下方式将它们添加到您的视图中:

let scrollView = UIScrollView()
let stackView = UIStackView()

scrollView.addSubview(stackView)
view.addSubview(scrollView)

记住在UIStackView和UIScrollView上设置translatesAutoresizingMaskIntoConstraints为false:

stackView.translatesAutoresizingMaskIntoConstraints = false
scrollView.translatesAutoresizingMaskIntoConstraints = false

为了让一切正常工作,UIStackView的尾随,领先,顶部和底部锚应该等于UIScrollView锚:

stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

但是UIStackView的宽度锚点必须等于或大于UIScrollView锚点的宽度:

stackView.widthAnchor.constraint(greaterThanOrEqualTo: scrollView.widthAnchor).isActive = true

现在锚定你的UIScrollView,例如:

scrollView.heightAnchor.constraint(equalToConstant: 80).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true

scrollView.bottomAnchor.constraint(equalTo:view.safeAreaLayoutGuide.bottomAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo:view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo:view.trailingAnchor).isActive = true 

接下来,我建议尝试以下设置UIStackView对齐和分布:

topicStackView.axis = .horizontal
topicStackView.distribution = .equalCentering
topicStackView.alignment = .center

topicStackView.spacing = 10

最后,你需要使用addArrangedSubview:方法来添加子视图到你的UIStackView。

文本Insets

另一个你可能会发现有用的特性是,因为UIStackView保存在UIScrollView中,你现在可以访问文本insets,使事情看起来更漂亮一点。

let inset:CGFloat = 20
scrollView.contentInset.left = inset
scrollView.contentInset.right = inset

// remember if you're using insets then reduce the width of your stack view to match
stackView.widthAnchor.constraint(greaterThanOrEqualTo: topicScrollView.widthAnchor, constant: -inset*2).isActive = true

我也想做同样的事情,偶然发现了这个优秀的帖子。如果您希望使用锚API以编程方式完成此操作,则可以采用这种方式。

总之,在UIScrollView中嵌入UIStackView,并设置UIStackView的锚约束来匹配UIScrollView的锚约束:

stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true