Stealing two-finger pan from mkmapview - iphone

I've placed a UIview above an MKMapView with the intention of stealing the two-finger pan from the map view when I am tracking a user's location. If you notice Google maps app does this on the phone as well.
But I'm at a loss as to how to do it. I want to be able to enable it and disable it at will depending on whether the location is being tracked or not. All other gestures and touches should be passed onto the mapview
thanks in advance.

Assuming you're going for OS 4 and above, the easy way is NOT to use a UIView, but instead to add a gesture-recognizer directly onto the mapview, e.g.:
UIPanGestureRecognizer* gest = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[mapView addGestureRecognizer:gest];
...and then all swipe gestures (in that case) would get passed to [self handlePanGesture:(UIPanGestureRecognizer*) x];
If you look in the docs around gesture recognizers, there's a wide variety of options, and you can add them to a pretty fine-level of granularity (tap vs swipe, how many fingers used, etc)

Related

How would I present a map view a specific region on first run?

If I want a map view to show a specific map region (which is the same each time the app launches?), how would I set that up?
Also, it is possible to prevent the user from scrolling away from this region, and also prevent the user from scrolling too far out?
1. Specific region
MKCoordinateRegion predefinedRegion;
[mapView setRegion:predefinedRegion animated:YES];
2. Prevent scrolling
mapView.scrollEnabled = NO;
3. Prevent zooming
mapView.zoomEnabled = NO;
If you just want to limit the zoom level it is a bit more complicated because zooming effectively changes the region. The best way to manage this is probably by using the MKMapViewDelegate protocol methods such as mapView:regionWillChangeAnimated:.
Cheers,
Sascha

UIButton with two state - touch and long touch

I'd like to make a button perform different methods, depending on if the user taps or does a long tap.
I've tried:
UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:#selector(doRewind)];
[uiNextButton addGestureRecognizer:longPress];
[longPress release];
But the app registers my touch only when I touch the button and move the finger a little bit.
What am I doing wrong?
If you are setting both a "normal" tap and a "long" tap gesture, there could be interactions between the two of them.
Have you tried setting the minimumPressDuration property for UILongPressGestureRecognizer?
Also, using requireGestureRecognizerToFail: can be useful to make one of the two gesture handler fire only if the other one did not.
Have a look at the relevant document for those two methods.
If this does not help, please, give more details about your view and all the gesture handlers you are defining.

Two fingered swipe v. one fingered drag in iOS

In my app I have a UIView derived class Canvas that uses touchesBegan: withEvent:, touchesMoved: withEvent:, and touchesEnded: withEvent: to draw in the canvas. I also want to use a swipe to load the previous (or next) canvas in an array. I tried setting up the following gesture (and a similar one for right):
UISwipeGestureRecognizer* leftSwipe = [[UISwipeGestureRecognizer alloc] initWithTarget: self action: #selector(pageFlipNext)];
leftSwipe.direction = UISwipeGestureRecognizerDirectionLeft;
leftSwipe.numberOfTouchesRequired = 2;
[_canvas addGestureRecognizer: leftSwipe];
[leftSwipe release];
But my two fingered swipes are still being treated as one-fingered drawing instructions.
How do I get my app to handle the two-fingered swipe correctly?
First of all, I would get started verifying whether _canvas.multipleTouchEnabled is set to YES. If it isn't, set it to YES.
You might also want to consider
leftSwipe.delaysTouchesBegan = YES;
This will delay the touches to be sent to the _canvas until the gesture fails. You can also use a UIPanGestureRecognizer and do something like this,
[pan requireGestureRecognizerToFail:leftSwipe];
I think that you can use UIPanGestureRecognizer
UIPanGestureRecognizer is a concrete
subclass of UIGestureRecognizer that
looks for panning (dragging) gestures.
The user must be pressing one or more
fingers on a view while they pan it.

iOS: Can I override pinch in/out behavior of UIScrollView?

I'm drawing a graph on a UIView, which is contained by a UIScrollView so that the user can scroll horizontally to look around the entire graph.
Now I want to zoom the graph when a user pinches in with two fingers, but instead of zooming in a view with the same rate for X and Y direction, I want to zoom only in the X direction by changing the X scale, without changing the Y scale.
I think I have to catch the pinch in/out gesture and redraw the graph, overriding the default zooming behavior.
But is there a way to do this?
I've been having a very difficult time to catch the pinch gesture on the UIScrollView, as it cancels the touches when it starts to scroll. I want the zooming to work even after the UIScrollView cancels the touches. :(
Thanks,
Kura
Although you cannot delete the existing pinch gesture recognizer, you can disable it and then add your own:
// Disable existing recognizer
for (UIGestureRecognizer* recognizer in [_scrollView gestureRecognizers]) {
if ([recognizer isKindOfClass:[UIPinchGestureRecognizer class]]) {
[recognizer setEnabled:NO];
}
}
// Add our own
UIPinchGestureRecognizer* pinchRecognizer =
[[UIPinchGestureRecognizer alloc] initWithTarget:self
action:#selector(pinch:)];
[_scrollView addGestureRecognizer:pinchRecognizer];
[pinchRecognizer release];
Then in
- (void) pinch:(UIPinchGestureRecognizer*)recognizer { .. }
use
[recognizer locationOfTouch:0 inView:..]
[recognizer locationOfTouch:1 inView:..]
to figure out if the user is pinching horizontally or vertically.
You should instead access the gestureRecognizers (defined in UIView), there are several of them being used by the scroll view,
figure out which one is the pinch recognizer and call removeGestureRecognizer: on the scroll view, then create your own and have it do the work, add it back with addGestureRecognizer:.
these are all public API,
the recognizers and what order they are in are not (currently),
so program defensively when accessing them
(this is a perfectly valid way to manipulate UIKit views, and Apple won't/shouldn't have issues with it - though they will not guarantee it works in any future release)
You should be able to subclass UIScrollView and override the touchesBegan: method. Don't call [super touchesBegan:] but instead, adjust the zoom as you like:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
//Anything you want. Probably you would want to store all the touches
//or their values, so that you can compare them to the touches
//in the touchesEnded: method,
//thus letting you know what the pinch amount was
}
If you like, you can judge whether it's a pinch or not, and if it's not, call the super method, and only handle it yourself for custom pinches.
Edsko & bshirley answers are good, but they don't tell where to place the code.
First, I placed it in viewDidLoad method, but no Pinch Gesture Recognizer was found in the scrollview (maybe because my scrollview is an IBOutlet).
Then I tried in viewWillAppear or viewDidAppear and the UIPinchGestureRecognizer was here.

OpenFlow AFItem UIImageView touchesBegan

I'm trying to use the OpenFlow project inside of my application.
My target is; when the user tab to any flow item which currently UIImageView according to OpenFlow's AFItemView, it will be zoom-in in the screen (with/without animation) and then user will be able to close and get back to cower flow view in the app.
I didn't get the tocuhesBegan event when I used the default OpenFlow library, then I saw this line
self.multipleTouchEnabled = NO;
self.userInteractionEnabled = NO;
self.autoresizesSubviews = YES;
in the AFOpenFlowView.m, when I change self.userInteractionEnabled = NO; to self.userInteractionEnabled = YES; I'm getting the touchesBegan event in the AFItemView.m that it already implement UIView, but flow doesn't work when I apply to this change.
I'm wondering where is the my mistake ?
Any help and example code would be appreciated.
Edit :
Let me explain my goal;
The target is user will open OpenFlow the scroll images with touch then when the touched any image that inside of the OpenFlow view, selected image will be come with zoom-in or flip or sth. animation. When the user touch to close icon which will be right side of the opened image, screen will be get back to the OpenFlow main screen, I did not find any solution to it on OpenFlow project. It's really urgent.
Regards
I've written this answer before: How to flick through a deck of cards?
The summary:
Once hitTest:withEvent: returns a non-nil value, it's over (by default); that view "owns" the touch (see UITouch.view). Only that view gets touchesBegan/Moved/Ended/Cancelled:withEvent: callbacks.
The touches are being grabbed by AFItemView, so AFOpenFlowView never gets touch events. It may be easier to add the necessary touch-handling to AFOpenFlowView instead.
Alternatively, you can implement touch-forwarding in AFOpenFlowView. It's a bit tricky to get right.