假设我在UIStackView中添加了更多可以显示的视图,如何制作UIStackView
滚动条?
答案 0 :(得分:459)
如果有人正在寻找无代码的解决方案,我创建了一个示例,使用自动布局在故事板中完全执行此操作。
您可以从github获取。
基本上,要重新创建示例:
UIScrollView
,并设置其约束。UIStackView
添加到UIScrollView
Leading
,Trailing
,Top
& Bottom
应与UIScrollView
Width
相同
UIStackView
和UIScrollView
之间设置相等的UIStackView
约束。 UIViews
UIStackView
.map()
答案 1 :(得分:37)
Apple的自动布局指南包含Working with Scroll Views的整个部分。一些相关的片段:
- 将内容视图的顶部,底部,前导和尾部边缘固定到滚动视图的相应边缘。内容视图现在定义 滚动视图的内容区域。
- (可选)要禁用水平滚动,请将内容视图的宽度设置为等于滚动视图的宽度。内容视图现在填充了 水平滚动视图。
- (可选)要禁用垂直滚动,请将内容视图的高度设置为等于滚动视图的高度。内容视图现在填充 水平滚动视图。
醇>
此外:
您的布局必须完全定义内容视图的大小(除外 在步骤5和6中定义的地方。 ...当内容视图高于滚动视图时,滚动视图启用垂直滚动。当内容视图比滚动视图宽时,滚动视图启用水平滚动。
总而言之,滚动视图的内容视图(在本例中为堆栈视图)必须固定到其边缘,并且的宽度和/或高度另有约束。这意味着必须在期望滚动的方向上(直接或间接)约束堆栈视图的内容,这可能意味着例如向垂直滚动堆栈视图内的每个视图添加高度约束。以下是如何允许垂直滚动包含堆栈视图的滚动视图的示例:
// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
答案 2 :(得分:13)
正如Eik所说,UIStackView和UIScrollView很好地协同工作,请参阅here。
关键是UIStackView处理不同内容的可变高度/宽度,然后UIScrollView可以很好地滚动/弹出该内容:
cp "$f" "$destinationPath/archive"
答案 3 :(得分:12)
最高投票答案中的限制对我有用,并且我已经粘贴了下面约束的图像,如我的故事板中所创建的那样。
我确实遇到了两个问题,但其他人应该知道:
在添加类似于接受答案中的约束后,我得到红色自动布局错误Need constraints for: X position or width
。这是通过添加UILabel作为堆栈视图的子视图来解决的。
我以编程方式添加子视图,因此我最初在故事板上没有子视图。要摆脱自动布局错误,请在故事板中添加子视图,然后在添加真实子视图和约束之前将其删除。
我最初尝试将UIButtons
添加到UIStackView。按钮和视图将加载,但滚动视图不会滚动。这是通过将UILabels
添加到堆栈视图而不是按钮来解决的。使用相同的约束,此视图层次结构使用UILabels滚动但UIButtons不滚动。
我对此问题感到困惑,因为UIButtons 做似乎有一个IntrinsicContentSize(由Stack View使用)。如果有人知道按钮为什么不起作用,我很想知道原因。
这是我的视图层次结构和约束,供参考:
答案 4 :(得分:9)
我为您提供正确的解决方案
对于Xcode 11 +
步骤1: 添加 ScrollView 并调整其大小
步骤2: 为滚动视图添加约束
第3步: 将 StackView 添加到ScrollView中,并调整其大小。
步骤4: 为StackView添加约束( Stask View-> Content Layout Guide->“ Leading,Top,Trailing,Bottom” )
步骤4.1: 正确约束-> 常数(...->常数= 0)
第5步: 为StackView添加约束( Stask View-> Frame Layout Guide->“ Equal Width ”)
第6步示例: 添加两个具有 HeightConstraints 和 RUN 的UIView
我希望它将对您有用
答案 5 :(得分:9)
我本来想做同样的事情并偶然发现excellent post.如果你想使用锚API以编程方式执行此操作,这就是你要走的路。
总结一下,将UIStackView
嵌入UIScrollView
,并设置UIStackView
的锚点约束以匹配UIScrollView
的约束:
stackView.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
stackView.trailingAnchor.constraintEqualToAnchor(scrollView.trailingAnchor).active = true
stackView.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
stackView.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
stackView.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
答案 6 :(得分:5)
只需将其添加到viewdidload
:
let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets
答案 7 :(得分:3)
用于水平滚动。首先,创建一个{
model: models.Categories,
as: 'nestedCategories',
include: [
{
model: models.Categories,
as: 'nestedCategories'
}
]
}
和一个UIStackView
并通过以下方式将它们添加到您的视图中:
UIScrollView
记住要在let scrollView = UIScrollView()
let stackView = UIStackView()
scrollView.addSubview(stackView)
view.addSubview(scrollView)
和translatesAutoresizingMaskIntoConstraints
上将false
设置为UIStackView
:
UIScrollView
要使所有工作正常进行,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
方法将子视图添加到UIStackView。
您可能会发现有用的另一个功能是,由于addArrangedSubview:
被保存在UIStackView
中,因此您现在可以访问文本插图,使外观看起来更漂亮。
UIScrollView
答案 8 :(得分:2)
有一个空白的全屏场景
添加滚动视图。从滚动视图控制拖动到基本视图,添加左右上下,全部为零。
在滚动视图中添加堆栈视图。从堆栈视图控制拖动到滚动视图,添加左右上下,全部为零。
将一个UILabel放入堆栈视图中。
为清楚起见,将背景颜色设为红色;将高度设置为100,并在堆栈视图中将间距设置为20。
现在设置UILabel的宽度:
令人惊讶的是,控制 - 从UILabel
拖动到滚动视图,不堆栈视图,并选择相等的宽度。
重复:
就这么简单。这是秘密。
你已经完成了。就这么简单。
提示:尝试在堆栈视图中添加一个新项目,例如,UIView(可能用作空格)。请注意,一切都出错了。实际上,您必须为每个新项目添加一个高度(例如,“100”)。每次添加新项目时,都必须以某种方式给它一个高度。
另一种看待它的方式:
在上面,它说:令人惊讶的是,将UILabels的宽度设置为滚动视图的宽度(而不是堆栈视图)。这非常有效。
可替换地...
请注意,堆栈视图左右固定到其父级滚动视图。试试这个:
所以你有两个选择:
或
要清楚,请执行其中一种方法,不要同时执行这两种操作。
答案 9 :(得分:2)
您可以尝试 ScrollableStackView :https://github.com/gurhub/ScrollableStackView
它的Objective-C和Swift兼容库。它可以通过CocoaPods获得。
示例代码(Swift)
import ScrollableStackView
var scrollable = ScrollableStackView(frame: view.frame)
view.addSubview(scrollable)
// add your views with
let rectangle = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 55))
rectangle.backgroundColor = UIColor.blue
scrollable.stackView.addArrangedSubview(rectangle)
// ...
示例代码(Objective-C)
@import ScrollableStackView
ScrollableStackView *scrollable = [[ScrollableStackView alloc] initWithFrame:self.view.frame];
scrollable.stackView.distribution = UIStackViewDistributionFillProportionally;
scrollable.stackView.alignment = UIStackViewAlignmentCenter;
scrollable.stackView.axis = UILayoutConstraintAxisVertical;
[self.view addSubview:scrollable];
UIView *rectangle = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 55)];
[rectangle setBackgroundColor:[UIColor blueColor]];
// add your views with
[scrollable.stackView addArrangedSubview:rectangle];
// ...
答案 10 :(得分:2)
为macOS Catalyst添加了一些新观点。由于macOS应用支持窗口大小调整,因此您的UIStackView
可能会从不可滚动状态转换为可滚动状态,反之亦然。这里有两点微妙的事情:
UIStackView
旨在适应所有可能的区域。UIScrollView
将尝试调整其边界大小,以解决导航栏(对于macOS应用程序为工具栏)下方新增加/丢失的区域。不幸的是,这将创建一个无限循环。我对UIScrollView
及其adjustedContentInset
并不十分熟悉,但是从其layoutSubviews
方法的登录中,我看到了以下行为:
UIScrollView
尝试缩小其边界(因为不需要工具栏下方的区域)。UIStackView
。UIScrollView
不满意,因此决定恢复到更大的范围。这对我来说很奇怪,因为从日志中看到的是UIScrollView.bounds.height == UIStackView.bounds.height
。UIStackView
。在我看来,两个步骤可以解决此问题:
UIStackView.top
与UIScrollView.topMargin
对齐。contentInsetAdjustmentBehavior
设置为.never
。在这里,我关注的是UIStackView
垂直增长的垂直滚动视图。对于水平对,请相应地更改代码。
希望它对以后的任何人都有帮助。在互联网上找不到任何人提及此事,这花了我很长时间才能弄清发生了什么。
答案 11 :(得分:0)
创建的示例项目同时处理垂直和水平轴滚动。
https://gitlab.com/muhasturk/bmh.example.stackinsidescroll.ios
答案 12 :(得分:0)
就我而言,stackView 中的视图数量是可变的,我想将项目居中。因此,例如,stackView 中有一个视图,我希望该视图位于屏幕中间,如果所有视图都无法容纳在屏幕内,我希望该视图可滚动。
这是我的视图层次结构。
所以我为按钮设置了固定宽度,然后为 stackView:
对于 containerView:
对于 scrollView:
scrollView 也嵌入在具有前导和尾随约束的视图中。
关于我用来解决这个问题的代码:
for index in 0...array.count - 1 {
if index == 0 {
firstButton.setTitle(title, for: .normal)
} else {
let button = UIButton()
button.setTitle(title, for: .normal)
stackView.addArrangedSubview(button)
stackView.setNeedsLayout()
}
}
containerView.layoutIfNeeded()
stackView.distribution = .fillEqually
stackView.spacing = 10
stackView.alignment = .fill
答案 13 :(得分:0)
在场景上放置滚动视图,并调整其大小以使其充满场景。然后,将堆栈视图放置在滚动视图内,然后将添加项目按钮放置在堆栈视图内。一切就绪后,设置以下约束:
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
代码:Stack View.Width = Scroll View.Width
是关键。
答案 14 :(得分:0)
如果有人在寻找水平滚动视图
func createHorizontalStackViewsWithScroll() {
self.view.addSubview(stackScrollView)
stackScrollView.translatesAutoresizingMaskIntoConstraints = false
stackScrollView.heightAnchor.constraint(equalToConstant: 85).isActive = true
stackScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
stackScrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
stackScrollView.bottomAnchor.constraint(equalTo: visualEffectViews.topAnchor).isActive = true
stackScrollView.addSubview(stackView)
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.topAnchor.constraint(equalTo: stackScrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: stackScrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: stackScrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: stackScrollView.bottomAnchor).isActive = true
stackView.heightAnchor.constraint(equalTo: stackScrollView.heightAnchor).isActive = true
stackView.distribution = .equalSpacing
stackView.spacing = 5
stackView.axis = .horizontal
stackView.alignment = .fill
for i in 0 ..< images.count {
let photoView = UIButton.init(frame: CGRect(x: 0, y: 0, width: 85, height: 85))
// set button image
photoView.translatesAutoresizingMaskIntoConstraints = false
photoView.heightAnchor.constraint(equalToConstant: photoView.frame.height).isActive = true
photoView.widthAnchor.constraint(equalToConstant: photoView.frame.width).isActive = true
stackView.addArrangedSubview(photoView)
}
stackView.setNeedsLayout()
}
答案 15 :(得分:0)
对于嵌套或单个堆栈视图,滚动视图必须使用根视图设置固定宽度。滚动视图内部的主堆栈视图必须设置相同的宽度。 [我的滚动视图低于视图忽略它]
在UIStackView和之间设置一个相等的宽度约束 的UIScrollView。
答案 16 :(得分:0)
垂直stackview / scrollview示例(使用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)
]
确保定义了每个子视图的高度!
答案 17 :(得分:0)
首先设计你的视图,最好是像Sketch或者得到一个 你想要什么作为可滚动内容的想法。
在此之后使视图控制器自由格式(从属性中选择) 检查员)并根据内在内容设置高度和宽度 视图大小(从大小检查器中选择)。
之后在视图控制器中放一个滚动视图,这是一个 逻辑,我发现它几乎一直在iOS中工作(它可能需要通过命令的文档,可以通过命令+点击该类或通过谷歌搜索获得)
如果您正在使用两个或更多视图,那么首先从一个视图开始,该视图已在前面介绍过或更原始,然后转到已经介绍的视图 以后或更现代。所以这里是滚动视图 首先介绍,首先从滚动视图开始,然后转到 堆栈视图。这里将滚动视图约束在其超视图的所有方向上设置为零。将所有视图放在此滚动视图中,然后将它们放在堆栈视图中。
使用堆栈视图时
首先从地面开始(自下而上),即,如果您在视图中有标签,文本字段和图像,然后首先布置这些视图(在滚动视图内),然后放置它们在堆栈视图中。
之后调整堆栈视图的属性。如果仍未实现所需视图,则使用另一个堆栈视图。
在创建视图后,在母堆栈视图和滚动视图之间设置约束,而约束子视图使用母堆栈视图堆栈视图。 希望到这个时候它应该可以正常工作,或者你可以从Xcode发出警告,提出建议,阅读它所说的内容并实现它们。希望你现在应该有一个符合你期望的工作观点:)。
答案 18 :(得分:0)
如果您有一个约束来将堆栈视图垂直居中在滚动视图中,只需将其删除即可。
答案 19 :(得分:-12)
将其放入UIScrollView
...