假设我在UIStackView中添加了更多可以显示的视图,我如何让UIStackView滚动?
当前回答
到2020年为止。
100%故事板或100%代码。
这个例子是垂直的:
下面是最简单的解释:
有一个空白的全屏场景 添加一个滚动视图。Control-drag从滚动视图拖到基本视图,添加左-右-上-下,全部为零。 在滚动视图中添加堆栈视图。从堆栈视图Control-drag到滚动视图,添加左-右-上-下,全部为零。 在堆栈视图中放置两个或三个标签。
为了清晰,标签的背景颜色为红色。设置标签高度为100。
现在设置每个UILabel的宽度: 令人惊讶的是,从UILabel控件拖动到滚动视图,而不是堆栈视图,并选择相同的宽度。
重复:
不要从UILabel控件拖动到UILabel的父控件,而是拖到祖父控件。(换句话说,一直到滚动视图,不要到堆栈视图。)
就是这么简单。这就是秘诀。
秘密提示——苹果臭虫: 只有一件物品是不行的!添加几个标签以使演示正常工作。
你就完成了。
提示:必须为每个新项添加高度。任何滚动堆栈视图中的每个项都必须具有固有大小(例如标签)或添加显式高度约束。
另一种方法:
回顾一下上面的方法:令人惊讶的是,将标签的宽度设置为滚动视图的宽度(而不是堆栈视图)。
这里有另一种方法……
从堆栈视图拖动到滚动视图,并添加一个“宽度相等”约束。这看起来很奇怪,因为你已经左右固定了,但这就是你怎么做的。不管看起来有多奇怪,这就是秘密。
所以你有两个选择:
令人惊讶的是,将堆栈视图中每个项的宽度设置为scrollview祖父类(而不是stackview父类)的宽度。
or
令人惊讶的是,设置一个“宽度相等”的stackview到scrollview -即使你有stackview的左右边固定到scrollview。
需要明确的是,只使用其中一种方法,不要同时使用两种方法。
其他回答
在你的场景中放置一个滚动视图,并调整它的大小,使它充满场景。然后,在滚动视图中放置一个堆栈视图,并在堆栈视图中放置添加项按钮。一旦一切就绪,就设置以下约束条件:
Scroll View.Leading = Superview.LeadingMargin
Scroll View.Trailing = Superview.TrailingMargin
Scroll View.Top = Superview.TopMargin
Bottom Layout Guide.Top = Scroll View.Bottom + 20.0
Stack View.Leading = Scroll View.Leading
Stack View.Trailing = Scroll View.Trailing
Stack View.Top = Scroll View.Top
Stack View.Bottom = Scroll View.Bottom
Stack View.Width = Scroll View.Width
代码:堆栈视图。宽度=滚动视图。宽度是关键。
我也想做同样的事情,偶然发现了这个优秀的帖子。如果您希望使用锚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
将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
这里投票最多的答案中的约束条件对我来说是有效的,我已经将在我的故事板中创建的约束条件的图像粘贴在下面。
我确实提到了两个问题,但其他人应该注意:
After adding constraints similar to those in in the accepted answer, I'd get the red autolayout error Need constraints for: X position or width. This was solved by adding a UILabel as a subview of the stack view. I'm adding the subviews programmatically, so I originally had no subviews on the storyboard. To get rid of the autolayout errors, add a subview to the storyboard, then remove it on load before adding your real subviews and constraints. I originally attempted to add UIButtons to the UIStackView. The buttons and views would load, but the scroll view would not scroll. This was solved by adding UILabels to the Stack View instead of buttons. Using the same constraints, this view hierarchy with the UILabels scrolls but the UIButtons does not. I'm confused by this issue, as the UIButtons do seem to have an IntrinsicContentSize (used by the Stack View). If anyone knows why the buttons don't work, I'd love to know why.
下面是我的视图层次结构和约束,供参考:
推荐文章
- 如何使用iOS创建GUID/UUID
- 禁用所呈现视图控制器的交互式撤销
- 点击按钮时如何打开手机设置?
- 如何使用UIVisualEffectView来模糊图像?
- 如何修复UITableView分隔符在iOS 7?
- 故事板中的自定义单元格行高设置没有响应
- 在Swift中使用自定义消息抛出错误/异常的最简单方法?
- 如何在Swift中获得唯一的设备ID ?
- 复制文本到剪贴板与iOS
- 在Swift中根据字符串计算UILabel的大小
- 如何调用手势点击在UIView编程在迅速
- 我如何隐藏在一个Swift iOS应用程序的状态栏?
- 在iPad上使用iOS 8正确呈现UIAlertController
- 尝试将一个非属性列表对象设置为NSUserDefaults
- 如何改变导航栏的颜色在iOS 7?