Cancel UIGestureRecognizer if subview contains gesture? - ios

I was originally using the UITouch methods (touchesMoved: withEvent:) in order to detect the movement in a view. Due to the fact that it seemed not to update often enough I switched to using a UIPanGestureRecognizer (though this didn't actually fix the initial problem).
After using this the touches received for movements responded no matter what it was touching (different subviews) which I actually prefer. However now I have an issue with all the subviews which have movement. I need the gesture recognizer to still move the view even while touching subviews, however if the subview also moves in this direction (left/right) I need my recognizer to cancel.
It seems like gestureRecognizerShouldBegin: might be somewhere to start, but in my case, I cannot account for all subviews.
Is it possible to make pan gesture recognizer cancel if the subview (i.e. another pan recognizer, UISlider, horizontal scrollview, etc.) touched needs to be moved in left/right directions without having to account for each subview individually?

Related

make superview respond to subView's UIPanGesture in some cases

I have a scrollView and it contains a subView. SubView has a panGesture added to it.
What I want:
I need pangesture to work on subview only if the panning is done vertically. If the panning happens horizontally, I want the scrollView to respond for the panning instead of subview. How can I acheive this
Note: Iam able to find programatically when the panning happens horizontally.
There are several ways to do this:
Depending on what your subview does, you maybe able to replace it with a scrollview and lock it to scroll only vertically. (while the super should scroll only horizontally).
You can try feeding the touch information from the subview to it's superview if the pan gesture is moving horizontally. You could do this using a delegate pattern or, if you know what you're superview is, just access superview in your subview. However, this creates a strong coupling between the two views and probably shouldn't be done. It would be fragile and many would consider it code smell.
(best option) - Subclass UIGestureRecognizer and create your own gesture recognizer that only recognizes vertical movement. Use that instead of the UIPanGestureRecognizer.
Option 3 is the best, but probably the most work. You'll want to read Apple's docs on subclassing UIGestureRecognizer: Apple Docs - UIGestureRecognizer.
I've also written my own drag gesture recognizer, FlxDragGestureRecognizer.m, FlxDragGestureRecognizer.h (similar to a pan gesture recognizer), which you can use if you'd like, or take a look at to get a good idea of how to subclass UIGestureRecognizer. You can use this class to recognize touches moving only in certain directions, otherwise it will fail (which will allow other gesture recognizer to recognizer, like the scrollview). It also has a lot of other customizations and information it gathers, like velocity.
Since you already know how to detect the panning, then in you will need to implement a delegate protocol in your superview, a delegate property in your subview and assign your superview as a delegate for your subview.
when detecting horizontal panning, call the delegate method, when detecting vertical panning, implement what you want in the subview.

Drag Gesture Recognizer interfere with swipe Gesture Recognizer

I have a problem about gesture recognizer. I have two gesture recognizers in my view, one added to the background superview to swipe to change background color, the other one is added to a subview which could be dragged around.
The problem is the drag gesture is interfered with the swipe. When I drag the view around, in some case, drag operation will be recognized as a swipe and trigger the swipe operation. I don't want this, I just want swipe could be recognized after finish this drag operation. This situation is more often when I drag the subview around quickly. Every time during the drag, the swipe operation will be triggered.
You need to setup your lesser UIGestureRecognizer with requireGestureRecognizerToFail: and pass your recognizer that you want to be important to it.
UIView *subview = ....
[self addSubview:subview];
[self.gestureRecognizer requireGestureRecognizerToFail:subview.gestureRecognizer];

Disable scroll in UIScrollView while multi touching

In my program I use two fingers to pinch (zoom in and out), so sometimes when I want to pinch, app scrolls.
I would like to don't let scrolling in UIScrollView while two or more touches are on screen. How can I achieve that?
Try using UIGestureRecognizer.
In you case you must use a UITapGestureRecognizer, with 2 finger and one tap.
Attach the gesture on the table view.

How do I pass delayed scroll gestures from a UIButton inside of a UIScrollView?

I have a UIScrollView that contains several UIButtons. Each button is wired up to take an action when the user inputs a touch up event, so they are able to place their finger on the button and it will not be selected until it is raised. Currently, if I made a swipe gesture to scroll the UIScrollView quickly, then the scroll view moves as expected even if the gesture happens directly over a UIButton. HOWEVER, if I hold my finger down too long on a UIButton (about 1 second), the UIScrollView will no longer recognize the gesture and will not be able to scroll until the finger is lifted up.
I am wondering if their is a way to always have the UIScrollView recognize the scroll gesture? Note that this is not an issue if I touch the UiScrollView in a location without a UIButton - it then scrolls as expected.
It may worth a try to let your UIButton respond to UIControlEventTouchDown (maybe with an empty action). I'm not sure if this will work, but conceptually I think it should let the UIButton capture the touch immediately.
(Also make sure you don't enable delaysContentTouches on your scrollview.)
I found the answer to this here: UIScrollview with UIButtons - how to recreate springboard?
Essentially, I had to extend UIScrollView and override touchesShouldCancelInContentView, having it always return YES.

How do I allow certain gestures to go through a superview to a view below it?

I have a view with three image views hangin' around. These image views respond to certain gestures. I want to allow a certain gesture (such as a swipe across the screen) to do an action to all of the imageviews (such as, say, delete them all).
The only way I can think of having the swipe gesture be recognized everywhere on the screen is by overlaying a clear superview that looks for swipe gestures. My problem; however, is that I don't know how to let the superview ignore all other gestures so I can still interact with the imageviews below. Is there an easier way to handle this problem?
Try adding the gesture to your view's window rather than the view:
[self.view.window addGestureRecognizer:gesture];

Resources