UICollectionView responding while being scrolled? - objective-c

I have a UICollectionView filled with some cells, and i implemented the method - (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
This works like a charm, but it doesn't work while it is scrolling. It is a problem since the scrolling is very sensitive, and thus when i mean to push a cell and call the method, i end up scrolling with no result.
So i was wondering how to counter this and came up with this:
Can i simply set the method to respond while it is scrolling?
If not - Can i simply make it so scrolling ONLY happens if you use for example 2 fingers? to seperate the 2 actions more.
Thanks on advance

The selection of a UICollectionViewCell happens when you tap it. A tap should be short and at one place. If you scroll instead, you're probably not tapping right. If this is the case, it would also happen while using built-in apps like Mail.
The UICollectionView uses a UITapGestureRecognizer to recognize selection of cells. This gesture recognizer doesn't allow specifics settings that might help you out in this case.
You might be able to change the UIPanGestureRecognizer to need 2 fingers, but you should really think about if that's what you want. You'd better use it the way Apple means it to be used, users are used to that.
That said, here's the documentation page on collection view's gesture support:
http://developer.apple.com/library/ios/#documentation/WindowsViews/Conceptual/CollectionViewPGforIOS/IncorporatingGestureSupport/IncorporatingGestureSupport.html
You might be able to use this to change the minimumNumberOfTouches property of the internally used UIPanGestureRecognizer. But again, I don't think you should.

Related

Pull to reveal hidden navBar-like menu in iOS? as seen in GetPocket App

I've been driving myself mad over this one. It might be one of those things where I need to take a step back and figure out the simplest way to implement this. Can't find anything on this either. I google-fu'd the heck out of this one.
In the Pocket App when you pull down a menu reveals itself just like the searchBar does. In this instance the faux bar when you pull it past its halfway point if you release it shows springs into place. If it is release before the halfway point the bar will snap back and hide. As shown here
In my case I've been trying to replicate this with no luck. In my case I have a UITextView inside of a UIViewController view. I think I have it all wrong.
I can get it to work with a UIScrollView hidden by initiating with it offscreen and then when I press a button the UIScrollView reveals itself. The problem is that this method covers everything so I'll have to resize and relayout a bunch of views. Is this in a UITableView possibly? I want it to be a pull action though and just want to put some TextStrings/Labels in this bar.
Thank you in advance.
Feels like you need a UIScrollView (or UITableView) and to put the menu you want to reveal at the top (in the table view header, for example) and then get the delegate callbacks for scrolling.
UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
You might also need to watch for some of the dragging delegate callbacks
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate
You can initially hide the menu by setting the content offset to the height of the menu, then catch the delegate callbacks for scrolling and, if the scrolling has reached beyond half the size of the menu set the content offset with animation.
- (void)setContentOffset:(CGPoint)contentOffset animated:(BOOL)animated
If I understand your goal correctly you don't need the scroll view.
What I would do is have an simple UIView containing all the stuff you need and place it outside of the visible area. This will be your pull-down view. Then add an UIPanGestureRecognizer to the view in your UIViewController and use it to track the movement of your finger and update the frame of the pull-down view accordingly. Then in this update method you simply check if the position has passed some threshold and if so you let the pull-down view snap to its final position (using animations of course).
If you are unfamiliar with the UIPanGestureRecognizer there is a really good tutorial here:
http://www.raywenderlich.com/6567/uigesturerecognizer-tutorial-in-ios-5-pinches-pans-and-more

Restricting UIScrollView scrolling to only one page at a time

I would like to limit a UIScrollView to only being able to scroll one page at a time.
In other words, even when the user flicks really fast, I want the UIScrollView to be restricted to scrolling only one page.
Is there a good way to do this?
UIScrollView *myScrollView;
...
myScrollView.pagingEnabled = YES;
When set to YES, the scroll view stops on multiples of the scroll view’s.
One way to achieve this, if you haven't already settled on the scroll view, is to use a UIPageViewController. I'm looking at one on my app and this functionality seems to come for free.
With the UIScrollView, I'm thinking you might want to respond to the UIScrollViewDelegate method - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
I was thinking you could hold your current 'page' in a property, and then in the scrollViewWillEndDragging:withVelocity:targetContentOffset: method you could modify the target content offset to only be the next/previous page.
There's a 2012 WWDC video, Enhancing User Experience with Scroll Views, that uses this approach if you wanted to see it in action.

UITableViewCell: deselect immediately after didSelect or when come back from pushed VC?

I've seen people doing this differently, I would prefer that when you select an item in UITableView (say in screen A), the item is highlighted(selected), and another screen B is pushed to the navigation stack, then when you go back from screen B to screen A, the previously selected item will be unselected with animation, so what you do is to put:
[self.tableView deselectRowAtIndexPath:[self.tableView indexPathForSelectedRow] animated:YES];
inside:
- (void)viewWillAppear:(BOOL)animated;
and this is what Apple's sample code does. But I've seen a lot of people deselecting the row just after it is selected, inside:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
I know it may be just a personal preference, but I wonder is there any official clarification on this? Deselecting in viewWillAppear: lets users know his/her previously selected item, which is a bonus, but for some custom cell, the selected background/view may not be just solid color, and they may have a UIView added to the cell to represent the selected state, which makes the app inconsistent if some cells are deselected with animation and some are straight away after selected without animation.
Does anyone have any idea?
It's something that's up to you, if you are customising your applications UI extensively then you might not want to use this highlight at all. Maybe you have a complex cell and instead of using the cells selection trigger to drill down into a detail view or other, maybe you'll have a UIButton inside you cell.
It seems to me that UIKit wants to highlight the cell and retain it's highlight until you pop the detail view controller, at this point, presumably in viewWillAppear:, the currently selected cell of the UITableView is deselected, this allows you to have a very subtle and brief indication of which cell was selected to access where you've just come from.
Doesn't sound too interesting said like that however imagine if you exit the app and return some hours later, it's nice to have this small and as I said very subtle animation.
In the applications I've done in the past I've tended to not use this so much, or select but deselect immediately, so the user doesn't see a deselection animation upon returning or going "back" to the list. But that said all my cells in the applications I'm referring to have been very heavily customised.

How to tell when a user taps in a UITableViewCell?

I'm working on an iOS app where I have UIWebviews inside UITableViewCells. The UIWebViews take up about 50% of the cell and the rest of the cell is blank. I need to be able to respond when a user taps in one of my cells. I've tried implementing the - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath method, but this only responds when a user taps in a part of my cell that does NOT contain a uiwebview. Is there any way in which I can respond to a tap regardless of where in my cell the user taped?
you can set userInteractionEnabled property of your UIWebView to NO, but in this case you will not be able to scroll it..
Your design is definitely bad: Apple explicitly says in the UIWebView class reference, that you should not add UIWebViews to table cells. Also, as the web view internally manages an UIScrollView, which captures all the touches. So the only way to do what you want is to subclass UIWebView and override the touch management methods. This is also not advisable, as UIWebView is one of the few classes which are not to be subclassed according to Apple.
You have to seriously reconsider your design pattern.
First, do this to your webview. Then, call the tableView's didSelectRowAtIndexPath method when a tap is registered. Kind of a pain, but the only way I can think of. This will allow the user to interact with the webview in a completely normal way, but sends lets the table know which cell is being interacted with. If that's not what you want, the other answers should work.
Try attaching a UITapGestureRecognizer to your cell.

how to write inside a cell of UITableView

How do I write inside a cell of UITableView using TouchesBegan and TouchesEnd methods?
A UITableView scrolls and so cells move. What you are talking about would pretty much prohibit a table from being able to scroll. Of course you could have a static table or some other table which never scrolls and so you think that's ok.
In that case, handling touch events in a UITableViewCell is the same as handling the touch events in any other UIView. You could use a add a UIGestureRecognizer to the view and pull interaction that way or access the information through the UIResponder.
On thing to remember is, make sure userInteractionEnabled is set to YES if you are going straight through the UIResponder otherwise you'll just end up ignoring the events.