The collection view has a frame of 320x400, and the cells have a size of 320x320. The collection view scrolls vertically with pagingEnabled = YES. So at any time you can see one cell and part of another cell below. When you scroll up, I need each cell to stop at y=0.
Right now what happens is that each time you page upward, the cell stops at a higher position on the screen and does not stop at y=0. I think this is because the collection view pages based on it's own height of 400. How can I override this to stop on each cell?
I've tried subclassing UICollectionViewFlowLayout and overriding targetContentOffsetForProposedContentOffset, but I can't get it to work. Is there an easier way?
You can set the Flowlayout's minimumLineSpacing to 60 (400 height-320 height). with paging on, that should give you perfect page.
Related
I have the following autolayout-driven setup:
Main viewController, with a scrollview inside it. Scrollview pinned to superview edges. This one scrolls up and down.
A few normal, fixed size views at the top of the scrollview
Another scrollview. This one scrolls left and right. The second scrollview contains a couple of tableviews, side by side. The idea is that the user can switch between them. They both contain a handful of cells, all the same width as the screen and 72pts tall.
The problem I'm trying to solve is that the tableview contents are not the same size. The left one has say, 6 cells, and the right one has 3.
My first approach was to dynamically change the second scrollview height to match which ever tableview was currently visible. What ended up happening was that switching between the two tableviews (by doing setContentOffset:animated:) went extremely wrong if animated was set to true - it would adjust the content offset so everything was offscreen. In fact it would set the content offset to and then as I switched, about a dozen times, then it'd reset. It was weird, I gave up.
Now I'm trying to just adjust the content inset of the main scrollview to offset the gap in the content of the current tableview, and it's also being weird. When I set the bottom content inset in viewDidLoad, it works fine. When I set it at the time the tableview becomes current, it does nothing.
What gives? What scenarios would lead to these view interactions not behaving properly?
Use different tableViewController for each table.
Embed them in pageViewController.
Add those few normal, fixed size views at the top of the pageViewControllers view.
Conform scrollViewDelegate in pageViewController.
Pass scrollViewDidScroll from tableViews to pageViewController.
Set tableViews inset to match those fixed size views at top.
Change height according to the scroll.
This is the way you can achieve the functionality you want.
I hope it helps.
I have a UITableView in the bottom of UIViewController and tableview height is 100 point now.
The tableview has 20 cells and tableview's header view is 100 point. And I've added a up UISwipeGestureRecognizer and a down UISwipeGestureRecognizer in table view header.
Now I want to change the tableview height constraint constant to 400 in up gesture action and change the tableview height constraint constant to 100 in down gesture action.
Now the problem is gesture recognizer isnt working in tableview
header when tableview scroll is enabled.
If tableview scroll is disabled then the gesture recognizer is
working. But unable to view all cells once the tableview height is
changed.
Here's a different approach. Don't use swipe gesture recognizers at all.
Instead, make the table always the full 400 points tall. Set its contentInset.top to 300. This will allow the table view to scroll so that only its top 100 points of content are visible at the bottom of the screen. Specifically, the table view will allow its contentOffset.y (which is its vertical scrolling position) to go down to -300 (instead of only down to 0). The table's content always starts at y = 0, so when the table's contentOffset.y is -300, only the top 100 points of its content are visible. As the contentOffset.y increases, more of its content becomes visible.
Then, override the table view's point(inside:withEvent:) method to return true only for points with y >= 0. This means the table will ignore (pass through) touches above its content when its content is scrolled so only the top 100 points are visible.
This is the final effect for a small table:
or for a big table:
You can find a detailed explanation (in Objective-C) and a link to the full test project (also in Objective-C) in this answer.
As it may help others, here is the simplest possible solution to this type of problem.
Extremely simple solution -
no tricks, nothing fancy -
don't have a "table view header".
Just make a new UIViewController
class TableWithRedTop: UIViewController
that has ...
[ red area .. swipe detection ]
[ main area - the table view]
Then simply put 'TableWithRedTop' inside a container view.
(Container view tutorial if you need one.)
In your MainView just have a call
func toggleTableHeight
When 'TableWithRedTop' gets a swipe, have one line of code to call toggleTableHeight in MainView
Note that in toggleTableHeight you can easily animate the height change, tilt it on an angle, duplicate it or do anything you want, as you're using a container view in MainView.
I'm going to make another suggestion that may solve the issue for you.
It could be what you want is an:
"self-expanding" table...
First implement the following with no animations, for simplicity.
You have two heights for the table, small and large.
Start the table on height small.
Remarkably, you only have to implement these two rules: just two simple lines of code:
Any time the user is scrolling upwards - in fact, change to "height large".
Any time the user is scrolling downwards, and, you are at the top position of the table (i.e. you can see cell #1) in fact change to "height small".
It's one of those things that is "so simple, it's hard to believe it works!"
It's sometimes referred to as a "pull-up table" I think.
(Note. If you're not familiar with detecting when the user is scrolling, fortunately it is trivial - code shown here for example.)
Set both swipe gesture’s cancelsTouchesInView to true and make sure that the gestures are added directly to the header and not the tableView.
That should do the trick, but so should adding a view with the gesture recognizes to the container view and setting it’s constraints to match the tableView’s top, left, and right constraints and setting its height to 100.
I have a horizontal-scrolling UICollectionView which is nested in a UIView that is centred and occupies 80% of the screen width.
I want the UICollectionView to be visible screen edge-to-edge rather than constrained to the super UIView bounds.
I have set the following which shows the UICollectionView across the screen width:
collectionView.clipToBounds = NO
...but when dragging the collectionView, it hides cells when they are completely outside of the super UIView bounds even though they are partially visible on the screen, which leads to a weird flickering of blank space/cell.
Ideally, I'd like a way to prevent the hiding of the cells completely out of bounds. Is there a way to do this?
The UICollectionView has a maximum size of 3 cells, so I'm not particularly worried about any performance implications of having all cells visible all the time.
The only way I found is to enlarge the frame of the collection view (and its superview in your case) and add contentInset's to it. You might also want to update scrollIndicatorInsets.
In my app, I have added an UITableView over a ScrollView. I have disabled scrolling in table view.
So, only the scrollView Scrolls, I have adjusted the scroll view content Size with the tableView Frame. So, I can access all the cells.
Consider, there are 5 rows visible in the screen, if I tap any of the row, the didSelectRowAtIndexPath method gets called. If I scroll down, say to 6th cell and tap on it. The method doesnt gets called.
Same issues happens with UIcollectionView.
The reason why I have added so is. When I scroll the Scroll View, a view in that should get fixed in the top and the tableView behind it should go on scrolling. You might have seen in many of the apps in Android. So, I have used the ScrollView didScroll delegate to get the offset position. As per it, I will make the view to be fixed and vice versa.
Make the height of UITableView same as the content height of table.
Then set the content size of UIScrollView as the height of UITableView
Here is a brief example to demonstrate
CGRect rect = tblTopics.frame;
rect.size.height = tblTopics.contentSize.height;
tblTopics.frame = rect;
self.scrlVwFacultyDtl.contentSize = CGSizeMake(self.scrlVwFacultyDtl.frame.size.width, tblTopics.frame.size.height);
In the above example the tblTopics is the instance of UITableView and scrlVwFacultyDtl is the instance of UIScrollView
hope it will help you..
The scrollView, which is there with UITableView dose not change it's size.
So I have a UITableView, where Cells are added by the User. Right after adding these cells, I'm calling
[self.tableView reloadData];
Now the tableView shows the new cells added by the User. fine. But, if the tableView get's larger, if it's too big to show everything in the view, it doesen't change the size of my scrollView. I have no scrollView in the view, aside from the "normal" scrollView, which comes with the UITableView. So I can't scroll to the last row, because the scrollView is "too small".
Is there anything I forgot? I'm thinking of something like
[self.tableView.scrollView reload];
I'm using the same concept in another class: The user is able to add cells and they're shown. But in the other class the scrollView "resizes" correctly.
I assume that you have table inside a scrollview. You need to change content size of scrollview after adding cells. Height of content size should change according to content in scrollview so that you can scroll through whole content.
Updated answer:
I think your tableview's frame is larger. It is crossing window's bounds. Try minimizing tableview's height.