Disable multi touches for a drawing view - ios

I have a view where I'm drawing lines. When I draw a line with two fingers or more, there is a weird behaviour. That's why I want to disable multi touch on this view.
I tried :
self.drawingView.multipleTouchEnabled = NO;
self.drawingView.exclusiveTouch = YES;
But there is no impact. And my the touches method are still called.
Ideally, I want to when I try to draw with two fingers, it does nothing. Is there a solution ?
Thanks :)

In your touches methods (Began/Moved) check how many touches are on screen and there is only one touch, handle it, otherwise pass it along. Example touchesMoved:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
if ((touches.count == 1) && ([event allTouches].count == 1)) {
// handle single finger touch moves here
....
} else {
// If more than one touch, pass it along
[super touchesBegan:touches withEvent:event];
}
}

Related

How can I find out if I have a UIView where I am long pressing as I move the touch point?

I am trying to figure out how I can determine if my touchpoint is where I have a UIView as subview or not. The background is UIView itself that I am adding multiple other UIViews to ... So as I long press and am changing the position while holding the touch, I'd like to know if there's a UIView at that point or not.
I have been thinking, still not clear how to go about it but came across this which makes me think of getting the indexes of hierarchy and check of it is larger than 1. But how could I do that for where I'm touching?
Any hint or clue would be appreciated.
You have to store both reference in two objects myParentView and mySubView now just use this method..
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
CGPoint locationPoint = [[touches anyObject] locationInView: myParentView];
UIView* viewYouWishToObtain = [self hitTest:locationPoint withEvent:event];
if(mySubView == viewYouWishToObtain){
//That view is touched
}else{
//That view is not touched
}
}

create custom annotation animation ios

I want to create custom annotation animations like in this app:- Easy Taxi iOS. In this app when the user is dragging the map, annotation is lifted a little. Then when dragging is stopped, it falls down from the lifted position with a nice animation.
So far i came to know that, I can use a static image in the center of my screen to show the movement on the map, & when i stop dragging the view(map) i have to build a custom animation for the annotation view.
So far i have implemented this code by which i am manipulating an Image to be hidden or shown on the map View in the center of the screen.
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
for (UITouch * touch in touches) {
CGPoint loc = [touch locationInView:self.mapView];
if ([self.mapView pointInside:loc withEvent:event]) {
self.mapKitAnnotationimageView.hidden=NO;
imageCheck=NO;
}
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
imageCheck=NO;
self.mapKitAnnotationimageView.hidden=YES;
}
-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animated{
if (!imageCheck) {
self.mapKitAnnotationimageView.image=[UIImage imageNamed:#"location"];
imageCheck=YES;
}
}
Any help regarding the custom animation will be greatly appreciated. I need this done in very short span of time.
Thanks for your time.

What is the proper way of passing UITouch * across multiple subviews?

I have a custom view that has multiple subviews. They are all circles on the screen, sort of like three wheels of different radius on top of each other. I'm trying to make them receive a UITouch * event correctly to make them spin with the finger. Since the shapes are actually squares on the screen, when a bigger one flips and it's touchable area enters the frame of a circle above, it becomes untouchable.
So, I created another subview on top of others that will calculate the distance of the touch point to the center and distribute the touch event accordingly. I can think of several ways of doing it, but I was wondering what would be the most elegant, and most correct way of handling a situation like this.
This is what I've done so far: My custom view has a delegate, and that delegate is assigned to my main viewController. I have three protocol methods in my custom view, for the three wheels respectively. I'm passing out the touch and event according to the point of UITouch, but I'm not sure how should I actually send this data to the views that are supposed to receive it. They are all custom UIControl objects, and they all handle touches via the -beginTrackingWithTouch:withEvent:. Since this is a private method, I cannot access this from my viewController. Should I make this method public and access this from the viewController, or is there a more correct way of handling this?
Edit: added the code:
This is how I distribute the touch in the custom UIView object. The calculations work fine.
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
//Distribute the touches according to the touch location.
UITouch *touch = [touches anyObject];
CGPoint point = [touch locationInView:self];
//calculations for the circles.
CGFloat xDistance = (point.x - BIGGEST_CIRCLE_RADIUS);
CGFloat yDistance = (point.y - BIGGEST_CIRCLE_RADIUS);
CGFloat distance = sqrtf((xDistance*xDistance) + (yDistance*yDistance));
//Check to see if the point is in one of the circles, starting from the innermost circle.
if (distance <= SMALLEST_CIRCLE_RADIUS) {
[self.delegate smallestCircleReceivedTouch:touch withEvent:event];
} else if (distance < MIDDLE_CIRCLE_RADIUS) {
[self.delegate middleCircleReceivedTouch:touch withEvent:event];
} else if (distance <= BIGGEST_CIRCLE_RADIUS) {
[self.delegate biggestCircleReceivedTouch:touch withEvent:event];
} else {
return;
}
}
The delegate is the viewController and the circles are custom UIControls. They handle the touch like this:
- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(UIEvent *)event {
CGPoint touchPoint = [touch locationInView:self];
{....}
return YES;
}
These work fine in themselves, but I'm not sure how should I connect the delegate method to the touch handling of each custom UIControl. Should I call their -beginTrackingWithTouch:withEvent: from the viewController, or should I make them implement the protocol of the customView? Or is there some other way to handle this properly?
Even I did not try it, it is not necessary, to do your own calculation. -hitTest:withEvent: should work fine for you.

Only allowing a single touchesMoved method triggered per period of time?

I am using touchesMoved with a coordinate system to detect and respond to user touches within certain areas of the screen. For example, if I have a virtual keyboard and the user swipes across the keys, it reads the coordinates and responds:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch * touch = [[event allTouches] anyObject];
CGPoint point = [touch locationInView:touch.view];
if(point.y < 333 && point.y > 166 && point.x < 90 && point.x > 20)
{
//do something
}
}
...However, the problem is, if the user slowly drags across the keys, or the border between keys, the method is triggered several times in a row, playing the piano key sound in a stutter.
How can I prevent this stutter? I think setting a minimum delay of 0.25 seconds between each successive if statement triggering would help. Also, this delay would only be for a specific if statement -- I want the user to be able to drag across the keys quickly and trigger different key's if-statement as quick as they want.
Does anyone know how to code something like this?
Try this:
BOOL _justPressed; // Declare this in your #interface
...
- (void)unsetJustPressed {
_justPressed = NO;
}
Then, in your touchesMoved:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
if (_justPressed) {
// A key was just pressed, so do nothing.
return;
}
else {
_justPressed = YES;
// Do stuff here
[self performSelector:#selector(unsetJustPressed)
withObject:nil
afterDelay:0.25];
}
}
This way, you set a variable _justPressed to YES every touchesMoved:withEvent: is called (or within a specific conditional in there, depending on what you want to do), and you use performSelector:withObject:afterDelay: to set _justPressed to NO after a certain time period, and so you can just check whether _justPressed is YES when touchesMoved: is called to ascertain whether it was called recently.
Remember, you don't have to return from the method like in the example above, you can simply use _justPressed to check whether you should play the sound, but still perform your other actions. The example is just to give you a basic idea of what to do.

Decrease Touch Area of UIButton

I am trying to decrease the touch area of an UIButton. Is that even possible? When the user touches on the button and drags his touch outside the buttton the touch event should stop immediately when the graphic of the button ends. Unfortunately the area is much bigger than the actual graphic. I found a lot things on how to increase the area but not how to make it smaller.
Thanks for your help.
I came up one solution. You can subclass UIButton and override touchesMoved: so that it recognize the touch to be ended if it was outside of the button. Here is my snippet.
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch * touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
if(!CGRectContainsPoint(self.bounds, touchPoint))
{
[super touchesEnded:touches withEvent:event];
}
else
{
[super touchesMoved:touches withEvent:event];
}
}
The drawback of this is that if you go out of the button and come back again, the button will not become active. But otherwise, I think it should work fine.

Resources