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


当前回答

苹果的自动布局指南包括了一个关于使用滚动视图的完整部分。一些相关片段:

Pin the content view’s top, bottom, leading, and trailing edges to the scroll view’s corresponding edges. The content view now defines the scroll view’s content area. (Optional) To disable horizontal scrolling, set the content view’s width equal to the scroll view’s width. The content view now fills the scroll view horizontally. (Optional) To disable vertical scrolling, set the content view’s height equal to the scroll view’s height. The content view now fills the scroll view horizontally.

此外:

你的布局必须完全定义内容视图的大小(除了 . ...当内容视图比滚动视图高时,滚动视图允许垂直滚动。当内容视图比滚动视图宽时,滚动视图启用水平滚动。

To summarize, the scroll view's content view (in this case, a stack view) must be pinned to its edges and have its width and/or height otherwise constrained. That means that the contents of the stack view must be constrained (directly or indirectly) in the direction(s) in which scrolling is desired, which might mean adding a height constraint to each view inside a vertically scrolling stack view, for example. The following is an example of how to allow for vertical scrolling of a scroll view containing a stack view:

// Pin the edges of the stack view to the edges of the scroll view that contains it
stackView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true

// Set the width of the stack view to the width of the scroll view for vertical scrolling
stackView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true

其他回答

只需将这个添加到viewdidload:

let insets = UIEdgeInsetsMake(20.0, 0.0, 0.0, 0.0)
scrollVIew.contentInset = insets
scrollVIew.scrollIndicatorInsets = insets

来源: https://developer.apple.com/library/ios/documentation/UserExperience/Conceptual/AutolayoutPG/LayoutUsingStackViews.html

如果有人正在寻找一个没有代码的解决方案,我创建了一个例子来完成这完全在故事板,使用自动布局。

你可以从github上得到。

基本上,要重新创建这个示例(用于垂直滚动):

创建一个UIScrollView,并设置它的约束。 添加一个UIStackView到UIScrollView 设置约束:前导,后尾,顶部和底部应该等于UIScrollView中的约束 在UIStackView和UIScrollView之间设置一个等宽约束。 在UIStackView上设置轴=垂直,对齐=填充,分布=等间距,间距= 0 添加一些uiview到UIStackView 运行

在第4步中将宽度交换为高度,并在第5步中设置轴=水平,以获得水平的UIStackView。

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

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

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

你可以试试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]; 
// ...

First and foremost design your view, preferably in something like Sketch or get an idea of what do you want as a scrollable content. After this make the view controller free form (choose from attribute inspector) and set height and width as per the intrinsic content size of your view (to be chosen from the size inspector). After this in the view controller put a scroll view and this is a logic, which I have found to be working almost all the times in iOS (it may require going through the documentation of that view class which one can obtain via command + click on that class or via googling) If you are working with two or more views then first start with a view, which has been introduced earlier or is more primitive and then go to the view which has been introduced later or is more modern. So here since scroll view has been introduced first, start with the scroll view first and then go to the stack view. Here put scroll view constraints to zero in all direction vis-a-vis its super view. Put all your views inside this scroll view and then put them in stack view.

当使用堆栈视图时

First start with grounds up(bottoms up approach), ie., if you have labels, text fields and images in your view, then lay out these views first (inside the scroll view) and after that put them in the stack view. After that tweak the property of stack view. If desired view is still not achieved, then use another stack view. If still not achieved then play with compression resistance or content hugging priority. After this add constraints to the stack view. Also think of using an empty UIView as filler view, if all of the above is not giving satisfactory results.

在创建视图之后,在母堆栈视图和滚动视图之间放置一个约束,同时约束子堆栈视图和母堆栈视图。 希望这个时候它能正常工作,否则你可能会从Xcode得到一个警告,给出建议,阅读它所说的并执行这些建议。希望现在你应该有一个工作视图按照你的期望:)。