How to create up/down swipeable UITableView? - ios

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.

Related

Nested UIScrollviews behaving strangely

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.

how to create a table with a fixed first column and row?

I'm trying to create a table with a fixed first column and row. I tried to implement it like the scheme below (it's a vertical UIScrollView with a horizontal UIScrollView inside). The problem is that I need to make them move together if I drag my finger across the screen diagonally with the acceleration and bouncing animations. I already tried creating a view on top, getting the movement with touchesBegan: and touchesMoved: and changing the contentOffset programatically but it has laggy and without acceleration and bounce. Any ideas? Thanks in advance
scheme:
From the first look:
Parent View: ScrollView with vertical Scroll only.
Inside:
First Row: UICollectionView (with horizontal scroll)
First Column: Normal UIView (or table view or colleciton view - depends on your setup)
The rest of cells: UICollectionView with horizontal scroll
Add an array value at the index path 0 manually. So that you will get a cell value constantly.

How can I make UITableView less sensitive to vertical scrolling?

I have table view that has more than 10 rows and inside each row I'm placing a hortizontally-scrolling scrollview (you can thumb through images much like in Coverflow).
The problem is that UITableView is too sensitive to vertical scrolling. When I'm trying to scroll left and right in a particular scrollview (inside of any cell), the table view starts scrolling up or down once it detects even the slightest movement of my finger upon the y-axis.
Is there a way I can change this and set a higher vertical-scroll threshold for the table view?
Here's a couple suggestions. Try them and see how they feel.
Suggestion 1
When you dequeue your tableViewCells, try calling this:
[tableView.panGestureRecognizer requireGestureRecognizerToFail:cell.scrollView.panGestureRecognizer];
Suggestion 2
Try setting this on your tableView:
self.tableView.delaysContentTouches = NO;
That property defaults to YES. It delays touches to the content of the table view cells by a fraction of a second, to help it recognize the difference between a tap and a drag.

Anchor a UIButton to the bottom of a UITableViewController's view

I have the following requirement. When a UITableViewController's view is displayed, there are a variable number of rows. Underneath the rows, a button should be displayed.
When the number of rows is small, the button should be anchored to the bottom of the view.
When the number of rows is larger, the delete button should be placed immediately after the last row.
In other words:
And not:
My best attempt at this so far has involved setting a tableFooterView and trying to update its height using the contentSize of the UITableView, but I am running into all sorts of problems. I might continue down this path and ask for some help, but first I want to know if anyone has alternative (better) solutions.
The result must play nicely with a double-sized status bar (during a call for example) and I am targeting iOS 6.0. I am not using interface builder.
One possible solution to achieve this effect might have to use two different solutions.
If the amount of rows means that the button will be off the screen then use the footerView like you have been doing.
If the amount of rows means that the button will not be off screen then
Add the button to the tableView
Implement - (void)scrollViewDidScroll:(UIScrollView *)scrollView and update the frame of the button to be offset from the bottom.
The offset from the bottom might follow some logic like this
yOffset = CGRectGetHeight(tableView.frame) - (CGRectGetHeight(button.frame) + somePadding)
yOffset += tableView.contentOffset.y
This would mean that the button still moves up and down with the scrolling but you don't have to mess with the footerView height
Keep both the table view and a button inside scroll view. Keep the button at the bottom of the scrollview. For proper scrolling to work you might want to set the scrollEnabled property of the scroll views. For more details on that check this up
Scrolling a UITableView inside a UIScrollView
EDIT:
yourView.autoresizingMask = UIViewAutoresizingFlexibleTopMargin ;
Check the accepted answer for this question for more details on implimenting struts and springs using code:
UIView autoresizingMask - Interface Builder to Code - Programmatically create struts and springs - Swift or Objective-C

Sticky UITableView, unnecessary horizontal bar is visible, and I can't scroll to the bottom of the table

I've created a UITableVIew and it is a subview of a UIView. There are three issues that i'm having and it is only occurring on iOS 4 devices:
1) The table doesn't bounce when the view hits either the top or bottom of the table while scrolling. The vertical bar doesn't shrink either, it feels sticky and it is very much acting like an Android table view. I've tried enabling the bounce property but that doesn't make any difference.
2) The horizontal scroll bar appears when the view is scrolled down to the bottom of the table. This shouldn't appear since the table view's contentSize has been set correctly. It does eventually disappear when the contentSize is set 20 pixels less than what it should be.
3) I can't scroll to the bottom of the footer view, and only half the footer view is visible.
I've added a UITableView as a subview to other views throughout my project and this has never occurred, and so i've copied the way that I create other UITableViews, but still no luck.
Any suggestions would be greatly appreciated.
Thanks,
Ankur
I worked out the problem. The problem is a little strange, although i had a feeling that the way i was coding was a little messy.
I am subclassing a View, and the parent view has a layoutSubview method, which is only calculating and setting the frame for a table view subview. In the subclass, i had to override layoutSubview for the same reason as the values for the table view's frame need to be different. This means that the table view's frame was being laid out twice, once by the parent class and a second time by the subclass. It seems that iOS 4 doesn't like this, and i should only set the frame once per subview per layoutSubview call.
Now i've created a layoutTableView method, which is called from the parents layoutSubview, and i've overridden layoutTableView in the subclass. Therefore the table view's frame is only being set once.

Resources