I have a pretty weird setup due to time restrictions and UI requirements.
The layout is pretty simple: the root view is a ScrollView, with a StackView in it. StackView has two elements, a header (which I wish to collapse), and the content (which is a custom tab bar, and below that, a container view for the tab bar's linked content).
Latter is constrained in height to the ScrollView, resulting in a kind of "sticky header" (the tab bar's top sticks to the navigation bar's bottom) and "collapsing header" (the header view is "collapsed", as it is scrolled out of the view).
This works fine, however I can't seem to find any information regarding how to handle scroll events. What I want is a "single" scrollable view with the tab bar being sticky.
The end result would work like this:
User starts scrolling, ScrollView handles scrolling up until the moment it "bottoms out", then hands over scrolling to the UITableView currently visible. When the user starts scrolling up, the UITableView currently visible scrolls until it hits the top, and immediately hands over scrolling to the outer ScrollView, which will then scroll down the tab bar and reveal the header.
On Android it's quite simple to implement, due to the Toolbar component's extendibility, but on iOS I'm dead in the water how to implement this. I've tried looking up scroll handover, but haven't found anything related to my issue - possibly I've used the wrong search query, but not sure.
How could I hand over the scroll event the easiest way?
Related
I have a scroll view which works fine. Almost. I'm building in Any/Any. The problem is that the scroll view won't scroll past the view controller. I have a switch that is mostly in the view controller window, but the rest is off the box (not really sure how to describe it; it's in the view in the scroll view, but the view is longer than the view controller so part of it is hidden).
The scroll view will scroll down until it hits the part where the view controller would end if you were looking at it in Xcode. There is some more stuff under the switch (labels and another switch). To view these you have to forcefully scroll down. Xcode shows no constraint errors (little red circle with white arrow).
Hopefully this makes sense
A ScrollView needs to know the height and width of the content it is holding in order to know how much to scroll and which direction. Here is a quick read on how ScrollViews work in iOS: https://www.objc.io/issues/3-views/scroll-view/
You can set this programmatically using the contentSize property, but this requires you to know and or calculate the contentSize, which is pretty tedious in most cases.
The correct way of defining the contentSize in iOS is to define AutoLayout constraints in your View. Here is an excellent tutorial on doing just that:
https://www.natashatherobot.com/ios-autolayout-scrollview/
I've been trying to replicate this effect for a couple days which was inspired by Tumblr.
I've previously asked questions on here with different approaches of the same problem but to no avail. I'm just curious as to how the engineers at Tumblr created a horizontal collection view, with two vertical collection views, and is able to scroll down without affecting the view above (without resetting the position of the view when you scroll vertically in a different tab).
Header Views
I tried this, but the header view was isolated and I had to scroll to the right to see the collectionView cells. This did not work.
Changing the topLayoutConstraint constant of my UIView (not cv header) with respect to the contentOffSet of the vertical collectionView.
This almost got the effect I wanted, except that when I scrolled horizontally, there was a huge gap between my collection view and if I scrolled in that new tab, the UIView would appear again because, again, topLayoutConstraint gets scrolled up depending on the contentOffSet of my vertical collectionView contentOffset.
Changing the position of the UICollectionView frame, and scrolling the super view up simultaneously with NSNotificationCenter.
Alas, this method did the same as method #2, except that the vertical collection view cells scrolled faster than the super view.
I ran out of options to make this work so I will show you in detail what's attempted to be replicated (also note the scroll bar on the right):
Note when I scroll down the first tab. I switch, and then scroll down further. Originally, as I've said, there would be a gap between the second main CV, and when I scrolled, the view would reposition as if were scrolling up again. On here, the view on top keeps going up. So I'm curious as to what method Tumblr engineers used to do this. UICollectionView inside UIScrollView? Other suggestions?
I believe there is no UICollectionView involved. It looks like UIPageViewController and each its page is a UITableView.
Perhaps the UIPageViewController sits in a UITableView as well - the header also moves up when you scroll. This main table has only one cell (and a header) which is occupied by the UIPageViewController.
Hope it helps.
I am trying to recreate a UIView I have seen in multiple apps, mainly Shazam. The top half of the screen has some interactive buttons, and the bottom half looks like a tableView with custom cells. When the bottom half is panned/swiped up, the tableView scrolls over the top half with velocity, much like a scroll view.
I have been researching this and experimenting for a couple days now. I have gotten close, but not quite there.
My last approach was a view that had a tableView inside it. When the view was panned, the view would move to wherever the finger moved it to, but then would not have any velocity afterwards. Also when the tableView was panned/swiped down, it wouldn't move the whole view down.
Before that I tried a scrollView that took up the whole length of the screen. That gave the desired effect, but the button wasn’t tappable, and you could scroll the view in the button area, which is undesired.
Does it utilize ScrollViews or is it using a tableView that acts much like a ScrollView somehow.
Here is the Shazam UI/UX I am looking to recreate:
The top portion has interactive buttons, and doesn’t scroll. The bottom half shows content and when scrolled, covers up the top portion.
Below is what I have tried so far: This one is the panning view, which sort of works, but doesn’t have velocity and the tableView doesn’t scroll the view back down.
Any thoughts on a direction I can take from here is greatly appreciated. I am using Swift.
Cheers
This sort of thing is perhaps best done with a collection view and a custom layout — you can have some items for which you set layout attributes absolute to the view, and others relative to the scroll content offset.
There's a great (if wandering) discussion of this and other techniques in the Advanced User Interfaces with Collection Views talk from WWDC 2014.
This is actually simple than it seems at first. Here's how you can achieve this:
Create a UIViewController (not a UITableViewController).
Add some buttons to the top area of the screen.
Add a table view spanning the entire view controller's view. Make sure the table view is on top of the buttons added in the previous step.
Configure the top cell of the table view to be transparent (by setting its background color to Clear). Set the background color on the table view to Clear as well. This way it won't obscure the elements at the top of the screen, unless the table is scrolled up.
Because your table view is now transparent, you'll need to explicitly set the background color on the table cells other than the top one.
Profit!
I have in the bottom of the screen a view containing 4 image views that I use as navigation buttons. That view is pinned to bottom layer by "0". Now my tableview is above this view and I have made a constraint of "10" from tableview to my "navigation view." I have two problems. When my tableview contains more rows than the screen can hold it puts the cells "behind" my "navigation view" even though I made the constraint it shouldn't. Now when I flip the screen to landscape mode it actually makes my navigation view disappear from the screen. I don't understand why as I pinned the bottom view to bottom layer. (2 questions)
Then of course my 2nd row decides to use much bigger font when I load in more rows, which is something I don't even want to bother you guys with yet, I think my simulator is playing tricks with me..
Anyway, I appreciate any help on my 2 problems above. Thank you
EDIT: Here I took some pictures:
http://i.imgur.com/LA9Spt0.png (this shows what i mean with the tableview pushing away the lower view even though the lower view is constrained to the bottom layer and the tableview has a constrain leading to the lower view (menu bar))
http://i.imgur.com/b6VoqFk.png Here what happens when I "pull" the tableview downwards to see more cells it blocks the upper label and top bar (which contains the logo I had to remove for reasons with the company) I tried to use :setBounces and setAlwaysVertBounces set to NO but then I can't scroll down the tableview when more cells exist.
(addition to img. nr 2)multiple cells makes the cells hide behind the lower menu navigation bar. I did make a constrain between the tableview and lower menu bar, shouldn't I be able to make the tableview "create" a scroll bar so u can scroll down instead of cells hiding behind the menu bar.
Thanks, any help much appreciated!
It sounds like you have some conflicts, or missing constraints.
You can see if you have constraints errors in the nib, in the 'view hierarchy' column in the left side of your nib, you will see a little red arrow..
Or that you have some conflict which you can see at the console when running you app.
Thanks
I currently have a UICollectionView with a header of a fixed size.
If you pull down then the header moves down leaving a gap above it between the header and the nav bar. The header has a button at the top, a couple of labels at the bottom and the BG is an image.
If you push up then the header scrolls upwards to display more of the UICollectionView items.
This is all working fine. However, we require a change to the behaviour.
What we want...
What we want is for the header to start off the same as it is now.
Pull down
But if you pull down the top of the "header" should stick to the nav bar and the header should grow.
I can do this easily by making the collection view frame smaller, faking a header and accessing the UIScrollViewDelegate methods in the controller.
Push Up
If you push up then the header should do exactly what it's doing now. i.e. stay the same size and disappear underneath the nav bar.
This last bit is tricky. If I go my proposed change for the pull down then it will make this much harder.
Question
How can I include both of these functions?
I'm thinking of maybe having a header but making it completely blank?
Another idea I just had... Make the collection view full screen but set the section inset so has enough space for the fake header. Then I can intercept the scroll view delegate methods like above?
I think this sounds best unless anyone has a better idea?
Can't you just make the header the desired (maximum) size but keep it hidden under the nav bar by calling scrollToItemAtIndexPath:atScrollPosition:animated: in viewWillAppear: of your UICollectionViewController?
As the UIScrollViewDelegate the controller could also take care of positioning the upper right button at the desired position while scrolling.