Is it possible to scroll through a UIStackView?

Let's say I added more views to the UIStackView that can be displayed, how can I scroll the UIStackView ?

+171
ios ios9 uiscrollview uistackview
Jul 28 '15 at 6:36
source share
16 answers

In case someone is looking for a solution without code , I created an example to do this completely in a storyboard using Auto Layout.

You can get it from GitHub .

Basically, to recreate the example:

  1. Create a UIScrollView and set its limits.
  2. Add UIStackView to UIScrollView
  3. Set limits: Leading , Trailing , Top & Bottom should be the same as in UIScrollView
  4. Set an equal Width constraint between UIStackView and UIScrollView .
  5. Set Axis = Vertical, Alignment = Fill, Distribute = Equal Interval and Interval = 0 in UIStackView
  6. Add multiple UIViews to UIStackView
  7. To run
+491
Feb 01 '16 at 17:06
source share

The Apple Auto-Layout Guide includes the entire section of Working with Scrolling Lists . Some relevant snippets:

  1. Connect the content views from the top, bottom, front and back edges with the scroll views of the corresponding edges. The content view now defines the scroll content area.
  2. (Optional) To disable horizontal scrolling, set the width of the content views to equal the scroll width. Now the content view fills the horizontal scroll view.
  3. (Optional) To turn off vertical scrolling, set the height of the content views equal to the height of the scroll views. The content view now fills the horizontal scroll view.

Further

Your layout should fully determine the size of the content view (except where specified in steps 5 and 6) .... When the content view is higher than the scroll view, the scroll view provides vertical scrolling. When the content view is larger than the scroll view, the scroll view allows horizontal scrolling.

To summarize, the presentation of the scroll content (in this case, the presentation of the stack) should be tied to its edges and have restrictions on width and / or height. This means that the contents of the stack view must be limited (directly or indirectly) in the direction (s) in which scrolling is required, which may mean, for example, adding a height limit for each view in the form of vertical scrolling of the stack. The following is an example of how to enable 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.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 
+40
Sep 12 '16 at 17:20
source share

As Eyk says, UIStackView and UIScrollView play great together, see here .

The key point is that UIStackView handles variable height / width for various content, and then UIScrollView does a good scroll / bounce of that content:

 override func viewDidLayoutSubviews() { super.viewDidLayoutSubviews() scrollView.contentSize = CGSize(width: stackView.frame.width, height: stackView.frame.height) } 
+13
Jul 29 '15 at 5:05
source share

The restrictions in the response to the upper voice worked for me here, and I inserted the image of the restrictions below as it was created in my storyboard.

I made two questions, although others should know:

  • After adding constraints similar to those included in the accepted answer, I get a red Auto Need constraints for: X position or width error Need constraints for: X position or width . This was solved by adding UILabel as a subview of the stack view.

    I add subviews programmatically, so I initially did not have any subzones on the storyboard. To get rid of autodetection errors, add a subview to the storyboard, then delete it at boot time before adding your real subviews and limitations.

  • I initially tried to add UIButtons to UIStackView. Buttons and views will be loaded, but scrolling will not scroll . This was resolved by adding UILabels to the Stack View instead of buttons. Using the same limitations, this view hierarchy is scrollable with UILabels, but UIButtons does not.

    I am confused by this problem as UIButtons really have IntrinsicContentSize (used by Stack View). If anyone knows why the buttons do not work, I would like to know why.

Here is my hierarchy and limitations for the link:

constraints for stack view in scroll view [1]

+13
Apr 22 '16 at 18:24
source share

I wanted to do the same and came across this. If you want to do this programmatically using the anchor API, this is the way to go.

To summarize, insert the UIStackView into the UIScrollView and set the UIStackView binding UIStackView according to the UIScrollView settings:

 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 
+9
Apr 14 '17 at 9:05
source share

Until 2019

100% storyboard OR 100% code.




Here is the simplest explanation:

  1. Empty full screen scene

  2. Add a scroll view. While holding down the Control key, drag from the scroll view to the base view , add all zero from left to right, top to bottom.

  3. Add a stack view to the scroll view. Hold the Control key, drag from the stack view to the scroll view , add left-right-top-bottom, all zero

  4. Put one UILabel in the stack view.

For clarity, make the background color red; set the height to 100 and in your stack view set the interval to 20.

  1. Now set the width of the UILabel:

    Surprisingly, dragging controls from UILabel to the scroll view, not the stack view, and select equal widths.

Repeat:

Do not control drag and drop from UILabel to the parent UILabel - go to Grandparents. (In other words, go all the way to the scroll view, don't go to the stack view.)

It is so simple. It's a secret.

  1. Then you should click on one UILabel, and you should literally click several times on copy-paste. It will not work with only one item. (DO NOT click duplicate, click copy, then paste.)

You made it so simple.

Tip: try adding a new element to the stack view of, say, UIView (possibly for use as a space). Please note that everything is going wrong. In fact, you have to add height to each new element (say "100"). Each time you add a new element, you must somehow indicate its height .




Another way to look at this:

Above this says: unexpectedly, set the width of the UILabels equal to the width of the scroll view (not the stack view). This works great.

On the other hand...

Note that the left and right view of the stack is attached to its parent, the scroll view. Try this:

Drag from the stack view to the scroll view and add a "width equal to" constraint. It seems strange because you are already pinned left and right, but that’s how you do it. Oddly enough, it seems like a secret.

So, you have two options:

  1. Surprisingly, set the width of the UILabels equal to the width of the progenitor scrollview (and not the parent stack ).

or

  1. Surprisingly, set the “width equal” to the stack as a scroll - even if you still have the left and right edges of the stack as a scroll.

To be clear, use ONE of these methods, DO NOT do both.

+7
Dec 05 '16 at 15:18
source share

Just add this to viewdidload :

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

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

+6
Dec 15 '15 at 13:35
source share

Horizontal Scrolling (UIStackView in UIScrollView)

For horizontal scrolling. First create a UIStackView and UIScrollView and add them to the view as follows:

 let scrollView = UIScrollView() let stackView = UIStackView() scrollView.addSubview(stackView) view.addSubview(scrollView) 

UIStackView not set translatesAutoresizingMaskIntoConstraints to false in UIStackView and UIScrollView :

 stackView.translatesAutoresizingMaskIntoConstraints = false scrollView.translatesAutoresizingMaskIntoConstraints = false 

For everything to work, the ending, leading, top and bottom UIStackView bindings must be equal to the 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 

But the width of the UIStackView binding must be equal to or greater than the width of the UIScrollView binding:

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

Now attach your UIScrollView , for example:

 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 

Next, I would suggest trying the following settings for aligning and distributing UIStackView :

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

Finally, you need to use the addArrangedSubview: method to add subviews to your UIStackView.

Text inserts

Another useful feature that may turn out to be useful is that since the UIStackView contained in the UIScrollView you now have access to text inserts to make everything look a bit prettier.

 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 
+5
Feb 07 '19 at 10:21
source share

You can try ScrollableStackView : https://github.com/gurhub/ScrollableStackView

This is the Objective-C and Swift library. It is available through CocoaPods .

Code Example (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) // ... 

Sample Code (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]; // ... 
+2
Dec 20 '16 at 19:52
source share

If you have a constraint to center the stack view vertically inside the scroll, just delete it.

0
Oct 10 '16 at 15:57
source share
  • First of all, create your own look, preferably in the form of a Sketch, or get the idea of ​​what you want as scrollable content.

  • After that, make a free form for the controller controller (select the inspector from the attribute) and set the height and width according to the internal content to the size of your view (selected from the size inspector).

  • After that, a scroll will appear in the view controller, and these are the logics that, as I discovered, work almost all the time in iOS (you may need to go through the documentation of this view class, which can be obtained using the command + click on this class or through googling)

    If you are working with two or more views, first start with a view that was introduced earlier or more primitively, and then move on to a view that was introduced later or more modern. So, since the scroll view was first enter scroll first, and then go to the stack. Here, set the limits for viewing scrolls to zero in all directions compared to the super view. Put all your views in this scroll view, and then put them as a stack.

While working with the stack view

  • First, start from the base up (approaching the bottom), i.e. if you have labels, text fields and images in your view, first lay out those views (inside the scroll), and then put them in the stack view.

  • After that, configure the stack view property. If the desired view has not yet been achieved, use a different view of the stack.

  • If still not achieved, play with compression resistance or content priority.
  • After that, add restrictions on the presentation of the stack.
  • Also consider using an empty UIView as a kind of filler if all of the above do not give satisfactory results.

After creating your view, set a restriction between the view of the mother stack and the scroll view, while viewing child elements with restrictions with the view of the mother stack. Hopefully by this time it should work fine, or you can get a warning from Xcode by offering suggestions, reading what it says, and implement them. Hopefully you should now have a working presentation in line with your expectations :).

0
Feb 18 '17 at 2:46 on
source share

Example for vertical stack / scroll view (using EasyPeasy for auto power off):

 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) ] 

Just make sure every height of your subspecies is determined!

0
Feb 24 '17 at 10:34 on
source share

For a nested or single stack scroll view, you need to set a fixed width with a root view. The main view of the stack, which is inside the scroll view, must have the same width. [My view of the scroll below the view ignore it]

Set an equal width limit between UIStackView and UIScrollView.

enter image description here

0
Feb 16 '18 at 15:28
source share

If someone is looking horizontally scroll

 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() } 
0
Jan 27 '19 at 9:01
source share

Place the scroll view on your scene and resize it so that it fills the entire scene. Then put the stack view in the scroll view and put the add item button in the stack view. Once everything is ready, set the following restrictions:

 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 

enter image description here

Code: Stack View.Width = Scroll View.Width is the key.

0
Aug 09 '19 at 1:22
source share

Put it in a UIScrollView ...

-13
Jul 28 '15 at 8:22
source share



All Articles