Gesture recognizer with Voice Over active - ios

I developed an application which allows to the user to draw his finger signature in a canvas.
This feature is implemented using UIPanGestureRecognizer with a specific target action to draw a line in a UIView, but when the “Voice Over” is active the gesture recognizer action is not triggered anymore.
Gesture initialize code
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(pan:)];
pan.maximumNumberOfTouches = pan.minimumNumberOfTouches = 1;
[self addGestureRecognizer:pan];
Gesture action code
- (void)pan:(UIPanGestureRecognizer *)pan {
CGPoint currentPoint = [pan locationInView:self];
CGPoint midPoint = midpoint(previousPoint, currentPoint);
if (pan.state == UIGestureRecognizerStateBegan)
{
[path moveToPoint:currentPoint];
}
else if (pan.state == UIGestureRecognizerStateChanged)
{
[path addQuadCurveToPoint:midPoint controlPoint:previousPoint];
}
previousPoint = currentPoint;
[self setNeedsDisplay];
}
Is there any way to draw a line in a view using gesture with “Voice Over” active?
Thanks and regards!

I resolved my problem setting both isAccessibilityElement and accessibilityTraits properties for UIView canvas:
canvasView.isAccessibilityElement = YES;
canvasView.accessibilityTraits = UIAccessibilityTraitAllowsDirectInteraction;

Related

Dragging coordinates with CGPoint

I want to get the coordinates from the user's finger while dragging. I tried this code, but it says the coordinates are always {0, 0},
What's wrong?
- (IBAction)Drag{
UIPanGestureRecognizer *Recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(dragged)];
[self.view addGestureRecognizer:Recognizer];
}
-(void) dragged{
UITouch *touch ;
CGPoint location = [touch locationInView:touch.view];
NSLog(#"%#", NSStringFromCGPoint (location));
}
I also tried NSLog(#"%.2f %.2f" location.x, location.y); and got the same.
Thanks
It's quite normal, you're using touch without having ever assigned a value to it.
The action for a gesture recognizer takes a parameter, which is the recognizer itself, which in turn has a locationInView: method, so you should use that. Also, you need to check the state of the recognizer. Finally, you probably don't want to add the gesture recognizer when you need it, just add it from the start.
// probably in your viewDidLoad
UIPanGestureRecognizer *Recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self
action:#selector(panGestureRecognizerAction:)];
[self.view addGestureRecognizer:Recognizer];
- (void)panGestureRecognizerAction:(UIPanGestureRecognizer *)recognizer
{
if (recognizer.state == UIGestureRecognizerStateBegan ||
recognizer.state == UIGestureRecognizerStateChanged)
{
CGPoint location = [recognizer.state locationInView:touch.view];
NSLog(#"%#", NSStringFromCGPoint (location));
}
}

UISwipeGestureRecognizer executes in an if/else statement when it should not

I am attempting to run an action in iOS 7 Sprite Kit when the user swipes the left half of the screen.
To accomplish this I created a for loop waiting for touch events and, on touch, there is an if statement that checks to see if the touch location is less than half of the view's bounds. The if statement itself is executing properly (the else half returns the proper NSLog if the touch is initiated on the right half of the screen). The action triggered by the UISwipeGestureRecognizer, however, is called regardless of where the touch is initiated. I have included a code sample below.
Is there is a reason this is not working as expected?
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInView:self.view];
NSLog(#"Touch location: %f, %f",touchLocation.x,touchLocation.y);
if (touchLocation.x<self.view.bounds.size.width/2) {
UISwipeGestureRecognizer *swipeRight = [[UISwipeGestureRecognizer alloc] initWithTarget:(self) action:#selector(screenSwipedRight)];
swipeRight.numberOfTouchesRequired = 1;
swipeRight.direction=UISwipeGestureRecognizerDirectionRight;
[self.view addGestureRecognizer:(swipeRight)];
UISwipeGestureRecognizer *swipeLeft = [[UISwipeGestureRecognizer alloc] initWithTarget:(self) action:#selector(screenSwipedLeft)];
swipeLeft.numberOfTouchesRequired = 1;
swipeLeft.direction=UISwipeGestureRecognizerDirectionLeft;
[self.view addGestureRecognizer:(swipeLeft)];
UISwipeGestureRecognizer *swipeUp = [[UISwipeGestureRecognizer alloc] initWithTarget:(self) action:#selector(screenSwipedUp)];
swipeUp.numberOfTouchesRequired = 1;
swipeUp.direction=UISwipeGestureRecognizerDirectionUp;
[self.view addGestureRecognizer:(swipeUp)];
}
else {
NSLog(#"Touches were on the right!");
}
}
}
-(void)screenSwipedRight
{
CGFloat percentToRight = 1-(self.playerOne.position.x / self.view.bounds.size.width);
NSTimeInterval timeToRight = self.horizontalRunSpeed * percentToRight;
NSLog(#"Percent to right = %f",percentToRight);
NSLog(#"Time to right = %f",timeToRight);
SKAction *moveNodeRight = [SKAction moveToX:self.view.bounds.size.width-self.playerOne.size.width duration:timeToRight];
[self.playerOne runAction:[SKAction sequence:#[moveNodeRight]]];
}
Is there is a reason this is not working as expected?
Yes. You are adding a new set of swipe gesture recognizers any time any touch begins on the left half of the screen. You are never removing them. You are never restricting the conditions for the gesture recognizer to begin.
This should fix your issue:
Delete your implementation of touchesBegan:withEvent:.
Add your gesture recognizers in viewDidLoad.
Set delegate = self for all of the gesture recognizers.
Add this code:
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
CGPoint touchLocation = [touch locationInView:self.view];
NSLog(#"Touch location: %f, %f",touchLocation.x,touchLocation.y);
BOOL shouldBegin = (touchLocation.x < self.view.bounds.size.width / 2);
return shouldBegin;
}

UITapGestureRecognizer and UIPanGestureRecognizer

I want to create and see a uiimageview when i tap the screen.
Before i lift the finger, i want to move the uiimageview around the screen and the image set only when i take the finger off. Heres what i did:
- (IBAction)tap:(UITapGestureRecognizer *)recognizer {
CGPoint location = [recognizer locationInView:self.view];
UIImageView *circle = [[UIImageView alloc] initWithFrame:CGRectMake(location.x, location.y, 50, 50)];
circle.userInteractionEnabled = YES;
[circle setImage:[UIImage imageNamed:#"monkey_1.png"]];
[self.view addSubview:circle];
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:circle action:nil];
[recognizer requireGestureRecognizerToFail:pan];
CGPoint translation = [pan translationInView:circle];
pan.view.center = CGPointMake(pan.view.center.x + translation.x, pan.view.center.y + translation.y);
[pan setTranslation:CGPointMake(0, 0) inView:self.view];
}
You can do this with just an UIPanGestureRecognizer or an UILongPressGestureRecognizer. In the gesture handling method, check the state property of the recognizer, and show your image when it's UIGestureRecognizerStateEnded (i.e. when the user lifts the finger from the screen). E.g.:
- (void)handleGesture:(UILongPressGestureRecognizer *)recognizer {
if(recognizer.state == UIGestureRecognizerStateEnded) {
// gesture ended: show the image
}
else if(recognizerState == UIGestureRecognizerStateBegan) {
// this code runs when the gesture is started.
}
else if(recognizerState == UIGestureRecognizerStateChanged) {
// gesture is in progress
}
}

Dragging Multiple Images

I am trying to develop an analysing app that determines if you are "clever"
What this involves doing is taking a picture of yourself and dragging points onto your face, where the nose, mouth and eyes are. However, The code I have tried does not work:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [[event allTouches] anyObject];
CGPoint location = [touch locationInView:self.view];
if ([touch view] == eye1)
{
eye1.center = location;
}
else if ([touch view] == eye2)
{
eye2.center = location;
}
else if ([touch view] == nose)
{
nose.center = location;
}
else if ([touch view] == chin)
{
chin.center = location;
}
else if ([touch view] == lip1)
{
lip1.center = location;
}
else if ([touch view] ==lip2)
{
lip2.center = location;
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesBegan:touches withEvent:event];
}
What is happening, because when I just have a single image, it works, but is not helpful for me. What can I do to make it work? The spots start at the bottom of the screen in a "Toolbar" and then the user drags them onto the face. I kinda want the finished result to look like:
There are two basic approaches:
You can use the various touches methods (e.g. touchesBegan, touchesMoved, etc.) in your controller or the main view, or you can use a single gesture recognizer on the main view. In this situation, you'd use touchesBegan or, if using a gesture recognizer, a state of UIGestureRecognizerStateBegan, determine locationInView of the superview, and then test whether the touch is over one of your views by testing CGRectContainsPoint, using the frame of the various views as the first parameter, and by using the location as the second parameter.
Having identified the view that the gesture began, then in touchesMoved or, if in a gesture recognizer, a state of UIGestureRecognizerStateChanged, and move the view based upon the translationInView.
Alternatively (and easier IMHO), you can create individual gesture recognizers that you attach to each of the subviews. This latter approach might look like the following. For example, you first add your gesture recognizers:
NSArray *views = #[eye1, eye2, lip1, lip2, chin, nose];
for (UIView *view in views)
{
view.userInteractionEnabled = YES;
UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:self action:#selector(handlePanGesture:)];
[view addGestureRecognizer:pan];
}
Then you implement a handlePanGesture method:
- (void)handlePanGesture:(UIPanGestureRecognizer *)gesture
{
CGPoint translation = [gesture translationInView:gesture.view];
if (gesture.state == UIGestureRecognizerStateChanged)
{
gesture.view.transform = CGAffineTransformMakeTranslation(translation.x, translation.y);
[gesture.view.superview bringSubviewToFront:gesture.view];
}
else if (gesture.state == UIGestureRecognizerStateEnded)
{
gesture.view.transform = CGAffineTransformIdentity;
gesture.view.center = CGPointMake(gesture.view.center.x + translation.x, gesture.view.center.y + translation.y);
}
}

How to detect or define the orientation of a pinch gesture with UIPinchGestureRecognizer?

I'm using UIPinchGestureRecognizer to detect pinch gestures, something like:
- (void) initPinchRecon {
UIPinchGestureRecognizer *pinchRecognizer = [[[UIPinchGestureRecognizer alloc]
initWithTarget:self
action:#selector(Perform_Pinch:)] autorelease];
[self addGestureRecognizer:pinchRecognizer];
[pinchRecognizer setScale:20.0f];
}
- (void) Perform_Pinch:(UIPinchGestureRecognizer*)sender{
NSLog(#"PINCH");
}
And it works well to detect a simple pinch gesture: It's possible to determine (or define myself) the angle or orientation of the pinch gesture ?, for example, to differentiate between an horizontal and an vertical pinch gesture ?
A very simple solution is to implement the gesture handler like this:
-(void)handlePinchGesture:(UIPinchGestureRecognizer *)recognizer {
if (recognizer.state != UIGestureRecognizerStateCancelled) {
if (recognizer.numberOfTouches == 2) {
CGPoint firstPoint = [recognizer locationOfTouch:0 inView:recognizer.view];
CGPoint secondPoint = [recognizer locationOfTouch:1 inView:recognizer.view];
CGFloat angle = atan2(secondPoint.y - firstPoint.y, secondPoint.x - firstPoint.x);
// handle the gesture based on the angle (in radians)
}
}

Resources