Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using a Stack View in a Scroll View and respecting Safe Area insets

I have a UIStackView inside a vertically scrolling UIScrollView with everything constrained using Auto Layout. The scroll view fills the superview, the stack view fills the scroll view, and various elements are added into the stack view. To allow this to play nicely with Auto Layout and define the scroll view's content size, you have to also specify the width of the stack view. That is done by adding a width constraint on the stack view, equal to the width of the scroll view. At this point nothing is ambiguous, it behaves exactly as desired.

Now, if you want to add margins so that the elements aren't stretching to the far left and right edges of the screen, you can change the leading and trailing constraint constants on the stack view to inset 15pt on both sides for example. But then you have to be sure to change the equal width constraint constant to -30. And that has worked well, insetting the scrollable contents, still allowing you to swipe at the far edges of the screen to scroll.

Now, the iPhone X comes along, and 15pt padding is no longer sufficient when in landscape because content is being placed underneath the housing sensor. So you need to update this to set the margins to respect the safe area layout margins. You really just want to use the default margins. You could change your stack view's leading and trailing constraint constants to use the view's layout margins (which respects the safe area insets), but this will not work because your equal width constraint constant is no longer double the amount of margins, the margins are dynamic now.

So, one way to resolve this is to create IBOutlets for the stack view's leading and trailing and width constraints, then programmatically adjust them all when the layout margins change (viewLayoutMarginsDidChange). But I'm wondering if there's a better approach, preferably a solution that works within in Interface Builder, no code required.

like image 455
Jordan H Avatar asked Sep 30 '17 18:09

Jordan H


People also ask

Does stack view scroll?

Scrolling only happens when the content view inside the scrollview is larger than the scrollview! To elaborate on point 6. If the stack view had no elements but all the constraints are in place, you get "Scroll View Need constraints for Y position or height".

When would you use a stack view?

Best use of stack view is that if you want to set multiple controls allinged vertically or horizontally to each other you just add all of them in stack view. stackview will handle its allignment you just need to give frame contraints to stackView.

What are stack views?

Overview. Stack views let you leverage the power of Auto Layout, creating user interfaces that can dynamically adapt to the device's orientation, screen size, and any changes in the available space. The stack view manages the layout of all the views in its arrangedSubviews property.

How do I use stack view auto layout?

Views and Constraints Begin by laying out the name rows in Interface Builder. Position the label and text field in their correct relative positions, select them both, and then click the Editor > Embed In > Stack View menu item. This creates a horizontal stack view for the row.


1 Answers

I found a way to do this entirely within Interface Builder. Instead of embedding the stack view within the scroll view directly, add a UIView inside the scroll view to be the content view. Create leading, trailing, top, and bottom constraints all equal to the superview with a constant of 0, plus an equal width constraint to the scroll view. Then embed the stack view inside this content view. Create leading and trailing constraints for the stack view equal to the superview's margin¹, plus top and bottom.

So your setup will be:

- view
-- scroll view
--- view
---- stack view

This will ensure on iPhone X in landscape you can scroll at the left and right edges, the scroll bar is placed at the far right edge of the screen, and the stack view is positioned within the safe area.

¹ I've found a constant of 8 adds enough padding to feel about right.

like image 171
Jordan H Avatar answered Oct 08 '22 04:10

Jordan H