Swift - StackView in ScrollView doesn't scroll - swift

I am trying to make a scrollable stack view inside a scrollview but it doesn't work.
I have built a structure like this:
If you can't see the image, this is the structure:
UIScrollView constrained to superview in all 4 directions
UIStackView (constrained to scrollview in all 4 directions + equal width)
Image Collection View (not constrained)
UIStackView (not constrained)
Stack of Labels (not constrained)
It doesn't scroll, can anyone see what I am missing?

You should set ContentView in your ScrollView with constraints like:
ScrollView's Constraints:
Leading to superView
Trailing to superView
Top to superView
Bottom to superView
These constraint's constants are 0
ContentView's Constraints:
Leading to superView
Trailing to superView
Top to superView
Bottom to superView
Equal height to ViewController's View (which is in the top of the view hierarchy)
Equal width to ViewController's View 
Note: You should set ContentView's height constraint's priority to 700 etc. (lower than default high value)
Attention:
Your stackViews and collectionView must have height for scrollable.
I hope it is works.
Enjoy.

Related

UIScrollView contentOffset resets when tapped

I have a UIScrollView which resets its contentOffset anytime the view is tapped.
This is demonstrated here: https://gyazo.com/c8fb5c0fa5b6d53acf45c809dcb5b251
What I've tried:
Disabling keyboard dismissal
Checking for isDragging on scrollViewDidScroll and resetting the content offset if it was false. This resulted in jumpy behavior.
Reading this question, it did not help.
You can test it yourself here: https://github.com/willbishop/scrollviewwizardry
Any ideas?
You could turn off paging if that is not the intended result you're looking for:
scrollView.isPagingEnabled = false
If paging is something you're looking to use:
Paging is meant for snapping between multiple views in a ScrollView, usually where each subview is the size of the ScrollView's bounds. Since you've enabled paging with vertical scrolling, and your ScrollView content height is less than two "pages" height, unexpected results from paging are occurring.
For your situation, if you set each view in your ScrollView equal to the ScrollView's height, and your ScrollView contentSize height is equal to its subview's combined height, then paging works properly and the content offset doesn't reset when tapped:
scrollView.frame.size.height = view.frame.height
subView1.frame.size.height = view.frame.height
subView2.frame.size.height = view.frame.height
scrollView.contentSize.height = subView1.frame.height + subView2.frame.height
It will snap between showing your two views when the ScrollView stops being scrolled. You could also have your "peekAmount" where the second view shows at the bottom while still scrolled to the top "page", as long as the height of your ScrollView contentSize is equal to twice the ScrollView bounds height (i.e. two pages).

How is scrollView page size calculated?

I have a scrollView embedded inside a UIView with a top constraint to the navigation bar.
My question is, how is the page size calculated of a UIScrollView (where scrollView.pagingEnabled = true)? I want each page to be the size of the aforementioned UIView, but it turns out that it's slightly bigger.
I set the contentSize as so in the view controller:
self.scrollView.contentSize = CGSizeMake(UIScreen.mainScreen().bounds.width, (UIScreen.mainScreen().bounds.height - 64) * 4)
I figured each page size would be UIScreen.mainScreen().bounds.height - 64 (because of the navigation bar and clock) but, like I said, the page turns out to be slightly bigger.
Try to set the height of the scrollView same as UIView that hosts it self.scrollView.superview.
Edit:
The 'slightly bigger' is probably the 64 points offset. You need to set self.automaticallyAdjustsScrollViewInsets = false inside yout viewController that hosts the scrollView to fix it

Vertically center subview using Auto-Layout

I'm trying to figure out how to center vertically a view using Auto-Layout.
I'm new to this technology so it makes me some problems...
This is my controller in Interface Builder:
The gray part is the superview and it contains a custom view (the yellow one) and a label (the red one); the yellow view is fixed at the bottom of the superview and it has fixe height and width. The red view has fixed width and height, too.
My goal is to center vertically my red view in the visible part of the gray view, whose visible height is superview.height - yellowView.height.
How can I do that?
Thank you so much!
The easiest way to do it, would be to make the gray view a subview of the main view too, and then you can just give the label a centerY constraint in IB or in code. If you can't so that for some reason, you can change the constant value of a centerY constraint in code, giving it a value of 1/2 the height of the yellow view. Give the label a centerY constraint in IB and make an IBOutlet to it (I call it centerCon in my example). The fixed height of my yellow view was 200.
- (void)viewDidLoad {
[super viewDidLoad];
self.centerCon.constant = 100;
}
One of the simplest solutions here will be like this:
redView.center = CGPointMake(superview.width/2, (superview.height - yellowView.height)/2);

How to adjust views using auto layout?

I am using AutoLayout in my sample app. I have three views, topView, middleView, bottomView.Following are the constraint I need,
topView:
Always start at x origin 10.
Left and right margin 10.
Height should vary based on screen bounds(or superview).
middleView:
There should be 10 px vertical margin between top and middle view.
Left and right margin 10.
Height should vary based on screen bounds(or superview).
bottomView:
There should be 10 px vertical margin between middle and bottom view.
Left and right margin 10.
Height should be constant, say 30.
I want that based on device screen size, bottom view y origin should change so that middle and top view size will adjust.
Problem here is there is no way to find out, what should be the y origin of bottom view and interface is providing permanent constraint like:
Top space to superview for middle view.
Top space to superview for bottom view.
This is because there is no way to find out the height of views.
Only difficulty is determining height for top and middle view.
You don't seem to care what the height of the top and middle view is, so I'm just going to make a decision for you: they will have the same height. Add the following contraints to the common superview of which these three views (_topView,_middleView and _bottomView) are subviews:
NSString *vfl = #"V:|-(10)-[topView]-(10)-[middleView]-(10)-[bottomView(==30)]-(10)-|";
NSDictionary *dict = #{#"topView":_topView,#"middleView":_middleView,#"bottomView":_bottomView};
NSArray *a = [NSLayoutConstraints
constraintsWithVisualFormat: vfl
options: 0
metrics: nil
views: dict];
Make sure you align them horizontally as well:
NSArray *b = [NSLayoutConstraints
constraintsWithVisualFormat: #"H:|-(10)-[topView]-(10)-|"
options: 0
metrics: nil
views: dict];
NSArray *c = [NSLayoutConstraints
constraintsWithVisualFormat: #"H:|-(10)-[middleView]-(10)-|"
options: 0
metrics: nil
views: dict];
NSArray *d = [NSLayoutConstraints
constraintsWithVisualFormat: #"H:|-(10)-[bottomView]-(10)-|"
options: 0
metrics: nil
views: dict];
Edit
The middle view will be a label, as you say. Labels have an intrinsic content size. If you don't set the height of this view, the autolayout system will know what to do instinctively. (Neat, right?) By pinning the top of _topView to the top of the superview and its bottom to the top of the label, its height should be automatically calculated. I have changed the code to reflect this.
Edit 2
In order to add constraints in code, find a common ancestor (superview) of these three views and write [superview addConstraints:a],[superview addConstraints:b], etc... Make sure that autolayout in IB is turned off and that you set the translateResizingMasksToConstraints to NO.

How to have a scrollview take the space between the uinavigationbar and the uitoolbar

I have a scrollview that I had to the view of the view controller pushed to a UINavigationController.
My navigation bar is opaque.
However, the scrollview seems to keep size of the whole parent view. I would like the scrollview to have the size of the space between the toolbar and the navigationbar.
Is this possible or do I have to hardcode some size values?
Thanks in advance
When you initialize your scrollView you can set its contentSize parameter:
[scrollView setContentSize:CGSizeMake(320,392)];
The height of the screen (480) minus the toolbar (44) and navigation bar (44) = 392. Drop that to 372 if you're also displaying the carrier status bar.
or, use the frame geometry properties:
[scrollView setContentSize:CGSizeMake((scrollView.superview.frame.size.width),
(scrollView.superview.frame.size.height -
toolbar.frame.size.height -
navigationController.navigationBar.frame.height))];
When you use autosize, the correct frame size is not known on viewDidLoad.
You should pack this inside viewWillAppear and then everything works fine
scrollView.contentSize = CGSizeMake(scrollView.superview.frame.size.width, scrollView.superview.frame.size.height);