touchesmoved leave frame - iphone

I am trying to figure out how I can set a button to not be highlighted when touchesmoved leaves the frame of the current selected button. See code below. The below code should allow any of the three buttons to be pressed individually and swipped. The problem I am having is that when the buttons a swipped eg using touchesmoved the buttons call the Actions but never set the buttons back to not be highlighted when the swipe leaves the button frame.
Thanks in advance,
Azza
- (void)touchesMoved: (NSSet *)touches withEvent:(UIEvent *)event {
for(UITouch *t in touches) {
CGPoint location = [t locationInView:t.view];
if((CGRectContainsPoint(Button1.frame, location)) && (!Button1.isHighlighted))
{
if (!Button1.isHighlighted){
[Button1 setHighlighted:YES];
[self doAction1];
}else{
[Button1 setHighlight:NO];
}
}
if((CGRectContainsPoint(Button2.frame, location)) && (!Button2.isHighlighted))
{
if (!Button2.isHighlighted){
[Button2 setHighlighted:YES];
[self doAction2];
}else{
[Button2 setHighlight:NO];
}
}
if((CGRectContainsPoint(Button3.frame, location)) && (!Button3.isHighlighted))
{
if (!Button3.isHighlighted){
[Button3 setHighlighted:YES];
[self doAction3];
}else{
[Button3 setHighlight:NO];
}
}
}
- (void)touchesBegan: (NSSet *)touches withEvent:(UIEvent *)event {
for(UITouch *t in touches) {
CGPoint location = [t locationInView:t.view];
if(CGRectContainsPoint(Button1.frame, location))
{
if (!Button1.isHighlighted){
[Button1 setHighlighted:YES];
[self doAction1];
}
}
if(CGRectContainsPoint(Button2.frame, location))
{
if (!Button2.isHighlighted){
[Button2 setHighlighted:YES];
[self doAction2];
}
}
if(CGRectContainsPoint(Button3.frame, location))
{
if (!Button3.isHighlighted){
[Button3 setHighlighted:YES];
[self doAction3];
}
}
}
- (void)touchesEnded: (NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *t in touches){
CGPoint location = [t locationInView:self.view];
if(CGRectContainsPoint(Button1.frame, location)) {
[Button1 setHighlighted:NO];
} else if(CGRectContainsPoint(Button2.frame, location)) {
[Button2 setHighlighted:NO];
} else if(CGRectContainsPoint(Button3.frame, location)) {
[Button3 setHighlighted:NO];
}
}
}

OK, I know I've handled this same issue before. I also see a reference to it in my own comments in the code. I've attached a chunk of very old code that I wrote to handle simulated buttons (similar to what you are doing). Maybe looking through this will help:
typedef struct {
BOOL enabled;
BOOL isActivated;
NSTimeInterval activatedStartTime;
NSTimeInterval holdTime;
CGRect frame;
UIImageView *glowImage;
BOOL processPending;
SEL callWhenTouched;
} SIM_BUTTON;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
int fingers = [touches count];
UITouch *touch;
CGPoint touchPoint;
int i, j;
for (i=0; i<fingers; i++)
{
touch = [[touches allObjects] objectAtIndex:i];
touchPoint = [touch locationInView:self.view];
for ( j=0; j<SIM_BUTTON_COUNT; j++)
{
if ( simButton[j].enabled && CGRectContainsPoint( simButton[j].frame, touchPoint) )
{
simButton[j].isActivated=YES;
simButton[j].activatedStartTime = [NSDate timeIntervalSinceReferenceDate];
simButton[j].processPending = YES;
}
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
int fingers = [touches count];
UITouch *touch;
CGPoint touchPoint;
CGPoint previousTouchPoint;
int i, j;
for (i=0; i<fingers; i++)
{
touch = [[touches allObjects] objectAtIndex:i];
touchPoint = [touch locationInView:self.view];
previousTouchPoint = [touch previousLocationInView:self.view];
for ( j=0; j<SIM_BUTTON_COUNT; j++)
{
if ( simButton[j].enabled && simButton[j].isActivated && CGRectContainsPoint( simButton[j].frame, touchPoint) && CGRectContainsPoint( simButton[j].frame, previousTouchPoint) )
{
simButton[j].isActivated=YES;
}
else
if ( simButton[j].enabled && !simButton[j].isActivated && CGRectContainsPoint( simButton[j].frame, touchPoint) && CGRectContainsPoint( simButton[j].frame, previousTouchPoint) )
{
simButton[j].activatedStartTime = [NSDate timeIntervalSinceReferenceDate];
simButton[j].isActivated=YES;
}
else
if ( simButton[j].enabled && simButton[j].isActivated && !CGRectContainsPoint( simButton[j].frame, touchPoint) && CGRectContainsPoint( simButton[j].frame, previousTouchPoint) )
{
simButton[j].isActivated=NO;
simButton[j].activatedStartTime = (NSTimeInterval)0.0;
}
else
if ( simButton[j].enabled && !simButton[j].isActivated && CGRectContainsPoint( simButton[j].frame, touchPoint) && !CGRectContainsPoint( simButton[j].frame, previousTouchPoint) )
{
simButton[j].isActivated=YES;
simButton[j].activatedStartTime = [NSDate timeIntervalSinceReferenceDate];
simButton[j].processPending = YES;
}
//
// If the user touched the SCAN button and then slid their finger off of the SCAN button
//
if ( scannerActive==YES && simButton[RIGHT_SCAN_BUTTON].isActivated==NO && CGRectContainsPoint( simButton[RIGHT_SCAN_BUTTON].frame, previousTouchPoint) )
{
phraseMode = EXTERNAL_SCAN_PHRASES; // Default
}
}
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
int fingers = [touches count];
UITouch *touch;
CGPoint touchPoint;
CGPoint previousTouchPoint;
int i, j;
for (i=0; i<fingers; i++)
{
touch = [[touches allObjects] objectAtIndex:i];
touchPoint = [touch locationInView:self.view];
previousTouchPoint = [touch previousLocationInView:self.view];
for ( j=0; j<SIM_BUTTON_COUNT; j++)
{
if ( simButton[j].enabled && simButton[j].isActivated && (CGRectContainsPoint( simButton[j].frame, touchPoint) || CGRectContainsPoint( simButton[j].frame, previousTouchPoint)) )
{
simButton[j].isActivated=NO;
simButton[j].activatedStartTime = (NSTimeInterval)0.0;
}
}
}
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[self touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event];
}

Related

How to detect in touchesEnded which nodes are still being pressed

I've been stuck on this problem for days. What I have is multiple SKSpriteNode's, one for a left arrow, right arrow and up arrow. When I hold down the right arrow I want my character to continue moving right while its being held down, on the other hand if you press the up Arrow then you will only jump once regardless of if you hold it down.
So my problem for example is when i hold the right arrow and then i press the up arrow, touchesEnded is called and it stops my character from moving right even though I still have my finger on the right arrow
-(void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
for (UITouch *touch in touches){
CGPoint location = [touch locationInNode:self];
if (CGRectContainsPoint(rightArrow.frame, location)){
[wizard setTexture:[SKTexture textureWithImageNamed:#"wizardRight"]];
didTouchRightArrow = YES;
isLookingRight = YES;
isLookingLeft = NO;
rightArrow.alpha = 0.5;
NSLog(#"Touching right");
}
if (CGRectContainsPoint(leftArrow.frame, location)){
[wizard setTexture:[SKTexture textureWithImageNamed:#"wizardLeft"]];
isLookingRight = NO;
isLookingLeft = YES;
didTouchLeftArrow = YES;
leftArrow.alpha = 0.5;
NSLog(#"Touching left");
}
if (CGRectContainsPoint(upArrow.frame, location)){
didTouchUpArrow = YES;
upArrow.alpha = 0.5;
NSLog(#"Touching up");
}
-(void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
[super touchesBegan:touches withEvent:event];
if (rightArrow.alpha != 1.0){
rightArrow.alpha = 1.0;
}
if (leftArrow.alpha != 1.0){
leftArrow.alpha = 1.0;
}
if (upArrow.alpha != 1.0){
upArrow.alpha = 1.0;
for (UITouch *touch in touches){
CGPoint location = [touch locationInNode:self];
if (CGRectContainsPoint(rightArrow.frame, location)){
NSLog(#"Touching right");
didTouchRightArrow = YES;
} {
NSLog(#"Not touching right");
didTouchRightArrow = NO;
}
if (CGRectContainsPoint(leftArrow.frame, location)){
NSLog(#"Touching Left");
didTouchLeftArrow = YES;
} else {
NSLog(#"not touching left");
didTouchLeftArrow = NO;
}
didTouchUpArrow = NO;
}
This may not be the right way to approach the problem, but in touchesEnded I am trying to see if the touch is still in the desired Rect.
You need a way to identify the different nodes which are registering a touch. There is more than one way to do this but I have always found using the name property of a node to be the simplest and easiest to work with.
You already have the right idea by using the BOOLs to register the touch states.
I wrote some code to handle what you are trying to accomplish:
#import "GameScene.h"
#implementation GameScene {
SKSpriteNode *node0;
SKSpriteNode *node1;
BOOL node0touch;
BOOL node1touch;
}
-(void)didMoveToView:(SKView *)view {
self.backgroundColor = [SKColor blackColor];
node0 = [SKSpriteNode spriteNodeWithColor:[SKColor redColor] size:CGSizeMake(100, 100)];
node0.name = #"node0";
node0.position = CGPointMake(100, 300);
[self addChild:node0];
node1 = [SKSpriteNode spriteNodeWithColor:[SKColor blueColor] size:CGSizeMake(100, 100)];
node1.name = #"node1";
node1.position = CGPointMake(400, 300);
[self addChild:node1];
node0touch = false;
node1touch = false;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:touchLocation];
if([node.name isEqualToString:#"node0"])
node0touch = true;
if([node.name isEqualToString:#"node1"])
node1touch = true;
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
for (UITouch *touch in touches) {
CGPoint touchLocation = [touch locationInNode:self];
SKNode *node = [self nodeAtPoint:touchLocation];
if([node.name isEqualToString:#"node0"])
node0touch = false;
if([node.name isEqualToString:#"node1"])
node1touch = false;
}
}
-(void)update:(CFTimeInterval)currentTime {
if(node0touch)
NSLog(#"node0 touch");
if(node1touch)
NSLog(#"node1 touch");
}

TableView didSelectRowAtIndexPath Not Being Called

On a UITableView, I used Custom Cells with this code:
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
gestureStartPoint = [touch locationInView:self.contentView];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.contentView];
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);
if(deltaX < kMinimumGestureLength && deltaY < kMaximumVariance&&!swiped){
//do something
NSLog(#"Tapped %d",indexRow);
//return YES;
} else if(deltaX < kMinimumGestureLength && deltaY < kMaximumVariance&&swiped) {
swiped = FALSE;
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.contentView];
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);
if(deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance){
//do something
NSLog(#"Swiped %d",indexRow);
gestureStartPoint = [touch locationInView:self.contentView];
swiped = TRUE;
}
else if(deltaY >= kMinimumGestureLength && deltaX <= kMaximumVariance){
//do something
}
}
Before I added this, didSelectRowAtIndexPath was being called, however, now it is not. I can comment out the section and it works fine. Anyone know a way to fix this?
EDIT: Posting the working code
Customcell.h
#define kMinimumGestureLength 30
#define kMaximumVariance 5
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#interface CustomCell : UITableViewCell {
UILabel *primaryLabel;
UILabel *secondaryLabel;
UIImageView *myImageView;
CGPoint gestureStartPoint;
int indexRow;
BOOL swiped;
}
#property(nonatomic,retain)UILabel *primaryLabel;
#property(nonatomic,retain)UILabel *secondaryLabel;
#property(nonatomic,retain)UIImageView *myImageView;
#end
CustomCell.m
#import "CustomCell.h"
#implementation CustomCell
#synthesize primaryLabel,secondaryLabel,myImageView;
- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
- (void)layoutSubviews {
[super layoutSubviews];
CGRect contentRect = self.contentView.bounds;
CGFloat boundsX = contentRect.origin.x;
CGRect frame;
frame= CGRectMake(boundsX+10 ,0, 50, 50);
myImageView.frame = frame;
frame= CGRectMake(boundsX+70 ,5, 200, 25);
primaryLabel.frame = frame;
frame= CGRectMake(boundsX+70 ,30, 100, 15);
secondaryLabel.frame = frame;
}
- (id)initWithFrame:(CGRect)frame reuseIdentifier:(NSString *)reuseIdentifier indexd:(int)indexd {
if (self = [super initWithFrame:frame reuseIdentifier:reuseIdentifier]) {
// Initialization code
primaryLabel = [[UILabel alloc]init];
primaryLabel.textAlignment = UITextAlignmentLeft;
primaryLabel.font = [UIFont systemFontOfSize:14];
secondaryLabel = [[UILabel alloc]init];
secondaryLabel.textAlignment = UITextAlignmentLeft;
secondaryLabel.font = [UIFont systemFontOfSize:8];
myImageView = [[UIImageView alloc]init];
[self.contentView addSubview:primaryLabel];
[self.contentView addSubview:secondaryLabel];
[self.contentView addSubview:myImageView];
indexRow = indexd;
}
swiped = false;
return self;
}
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
gestureStartPoint = [touch locationInView:self.contentView];
// [super touchesbegan];
[super touchesBegan:touches withEvent:event];
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.contentView];
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);
if(deltaX < kMinimumGestureLength && deltaY < kMaximumVariance&&!swiped){
//do something
NSLog(#"Tapped %d",indexRow);
[super touchesEnded:touches withEvent:event];
//return YES;
} else if(deltaX < kMinimumGestureLength && deltaY < kMaximumVariance&&swiped) {
swiped = FALSE;
}
//[super touchesEnded];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
UITouch *touch = [touches anyObject];
CGPoint currentPosition = [touch locationInView:self.contentView];
CGFloat deltaX = fabsf(gestureStartPoint.x - currentPosition.x);
CGFloat deltaY = fabsf(gestureStartPoint.y - currentPosition.y);
if(deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance){
//do something
NSLog(#"Swiped %d",indexRow);
gestureStartPoint = [touch locationInView:self.contentView];
swiped = TRUE;
//[self.superview.dataSource editCell];
}
else if(deltaY >= kMinimumGestureLength && deltaX <= kMaximumVariance){
//do something
}
//[super touchesMoved];
}
#end
I'm not 100% certain, but I think you need to call the super methods in order to continue to have the default behavior.
[super touchesBegan:...];
[super touchesEnded:...];
[super touchesMoved:...];
Each in it's own method.
This seems to be similar to this question. try calling the parent methods with [super touchesbegan] et al.

touch events problem

I found a very strange problem while handling touch events. The idea of an app is that i have an ImageView which contains a circle with text, that the user can rotate.
I've implemented a custom UIScrollView subclass to contain circle image. There i implemented methods touchesBegan, touchesMoved and touchesEnded in order to rotate my circle when user drags it left or right. Everything works fine, but when you try to drag it with one finger very fast from one side to another and in opposite direction, methods touchesBegan and touchesEnded are called different number of times. For example touchesBegan was called 1 time and touchesEnded 2 - 3 times. How can it be?
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if([[event touchesForView:self] count]==1){
touchPoint = [[touches anyObject] locationInView:self];
previousTouchPoint = touchPoint;
angle = 0;
if (((touchPoint.x > 160)&&(touchPoint.y < 210))||((touchPoint.x < 160)&&(touchPoint.y > 210))) {
leftRotation = YES;
}
else {
leftRotation = NO;
}
currentMoveAngle = 0;
}
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event{
if([[event touchesForView:self] count] == 1){
CGPoint newPoint = [[touches anyObject] locationInView:self];
CGPoint origin;
if (self.tag == 2) {
origin = CGPointMake(self.bounds.origin.x+self.bounds.size.width*0.5, 215);
}
else {
origin = CGPointMake(self.bounds.origin.x+self.bounds.size.width*0.5, 215);
}
previousTouchPoint.x -= origin.x;
previousTouchPoint.y -= origin.y;
CGPoint second = newPoint;
second.x -= origin.x;
second.y -= origin.y;
CGFloat rotationAngle = [self rotationFromFirstPoint:previousTouchPoint toSecondPoint:second];
previousTouchPoint = newPoint;
[self rotateContentToAngle:rotationAngle animated:NO];
currentMoveAngle += rotationAngle;
}
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{
if ([[event touchesForView:self] count] == 1){
rotating = YES;
CGFloat rotationAngle;
CGPoint origin = CGPointMake(self.bounds.origin.x+self.bounds.size.width*0.5, 215);
CGPoint lastPoint = [[touches anyObject] locationInView:self];
CGPoint touchP = touchPoint;
if ((touchP.x != lastPoint.x)||(touchP.y != lastPoint.y)) {
touchP.x -= origin.x;
touchP.y -= origin.y;
lastPoint.x -= origin.x;
lastPoint.y -= origin.y;
if (fabs(currentMoveAngle)>M_PI/6) {
NSInteger index = (int)trunc(currentMoveAngle/(M_PI/3));
currentMoveAngle-=(M_PI/3)*index;
NSLog(#"rotation index: %i",index);
}
if (leftRotation) {
rotationAngle = M_PI/3;
rotationAngle-=currentMoveAngle;
}
else {
rotationAngle = (-1)*M_PI/3;
rotationAngle-=currentMoveAngle;
}
[self rotateContentToAngle:rotationAngle animated:YES];
}
}
}
UIScrollView handle touch event very badly.... may be it is happening because of dragging of scrollView.
try this
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
if (!self.dragging){
if([[event touchesForView:self] count]==1){
touchPoint = [[touches anyObject] locationInView:self];
previousTouchPoint = touchPoint;
angle = 0;
if (((touchPoint.x > 160)&&(touchPoint.y < 210))||((touchPoint.x < 160)&&(touchPoint.y > 210))) {
leftRotation = YES;
}
else {
leftRotation = NO;
}
currentMoveAngle = 0;
}
}
}
- (void)touchesMoved:(NSSet*)touches withEvent:(UIEvent*)event{
if (!self.dragging){
if([[event touchesForView:self] count] == 1){
CGPoint newPoint = [[touches anyObject] locationInView:self];
CGPoint origin;
if (self.tag == 2) {
origin = CGPointMake(self.bounds.origin.x+self.bounds.size.width*0.5, 215);
}
else {
origin = CGPointMake(self.bounds.origin.x+self.bounds.size.width*0.5, 215);
}
previousTouchPoint.x -= origin.x;
previousTouchPoint.y -= origin.y;
CGPoint second = newPoint;
second.x -= origin.x;
second.y -= origin.y;
CGFloat rotationAngle = [self rotationFromFirstPoint:previousTouchPoint toSecondPoint:second];
previousTouchPoint = newPoint;
[self rotateContentToAngle:rotationAngle animated:NO];
currentMoveAngle += rotationAngle;
}
}
}
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event{
if (!self.dragging){
if ([[event touchesForView:self] count] == 1){
rotating = YES;
CGFloat rotationAngle;
CGPoint origin = CGPointMake(self.bounds.origin.x+self.bounds.size.width*0.5, 215);
CGPoint lastPoint = [[touches anyObject] locationInView:self];
CGPoint touchP = touchPoint;
if ((touchP.x != lastPoint.x)||(touchP.y != lastPoint.y)) {
touchP.x -= origin.x;
touchP.y -= origin.y;
lastPoint.x -= origin.x;
lastPoint.y -= origin.y;
if (fabs(currentMoveAngle)>M_PI/6) {
NSInteger index = (int)trunc(currentMoveAngle/(M_PI/3));
currentMoveAngle-=(M_PI/3)*index;
NSLog(#"rotation index: %i",index);
}
if (leftRotation) {
rotationAngle = M_PI/3;
rotationAngle-=currentMoveAngle;
}
else {
rotationAngle = (-1)*M_PI/3;
rotationAngle-=currentMoveAngle;
}
[self rotateContentToAngle:rotationAngle animated:YES];
}
} }
}
or make scrollingEnabled property NO.

iPhone - Gestures on UIPickerView and UIWebView

I'm making an iPhone app in which the user can do gestures (left and right swipes) to flick through tabs. My problem is that some of the pages have views such as the pickerview, webview, textfields and buttons. The swipes don't work on these. Is there any way to have global gestures?
For reference, my gesture code example:
//Swipe between tabs
#define mindrag 100
CGPoint mystartTouchPosition;
BOOL isProcessingListMove;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = [touches anyObject];
CGPoint newTouchPosition = [touch locationInView:self.view];
if(mystartTouchPosition.x != newTouchPosition.x || mystartTouchPosition.y != newTouchPosition.y) {
isProcessingListMove = NO;
}
mystartTouchPosition = [touch locationInView:self.view];
[super touchesBegan:touches withEvent:event];
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch = touches.anyObject;
CGPoint currentTouchPosition = [touch locationInView:self.view];
// If the swipe tracks correctly.
double diffx = mystartTouchPosition.x - currentTouchPosition.x + 0.1; // adding 0.1 to avoid division by zero
double diffy = mystartTouchPosition.y - currentTouchPosition.y + 0.1; // adding 0.1 to avoid division by zero
if(abs(diffx / diffy) > 2.5 && abs(diffx) > mindrag)
{
// It appears to be a swipe.
if(isProcessingListMove) {
// ignore move, we're currently processing the swipe
return;
}
if (mystartTouchPosition.x < currentTouchPosition.x) {
isProcessingListMove = YES;
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:1];
return;
}
else {
isProcessingListMove = YES;
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:3];
return;
}
}
else if(abs(diffy / diffx) > 1)
{
isProcessingListMove = YES;
[super touchesMoved:touches withEvent:event];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
isProcessingListMove = NO;
[super touchesEnded:touches withEvent:event];
}
// End of swipe
Any input is appreciated.
You can subclass UIImagePickerController and UIWebView and add these gesture capturing views to them, so long as you gesture detection can still pass touches to the underlying views of course.

Multi touch is not working perfectly on UIImageView

I am doing multi touch on UImageView means zoom in and zoom out on image view. I am using followng code but it doesn't work very well. Can anyone look at this code,
#import "ZoomingImageView.h"
#implementation ZoomingImageView
#synthesize zoomed;
#synthesize moved;
define HORIZ_SWIPE_DRAG_MIN 24
define VERT_SWIPE_DRAG_MAX 24
define TAP_MIN_DRAG 10
CGPoint startTouchPosition;
CGFloat initialDistance;
- (id)initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
// Initialization code
moved = NO;
zoomed = NO;
}
return self;
}
- (void)drawRect:(CGRect)rect {
// Drawing code
}
- (void)dealloc {
if([timer isValid])
[timer invalidate];
[super dealloc];
}
- (void) setImage: (UIImage*)img
{
zoomed = NO;
moved = NO;
self.transform = CGAffineTransformIdentity;
[super setImage:img];
}
- (CGFloat)distanceBetweenTwoPoints:(CGPoint)fromPoint toPoint:(CGPoint)toPoint {
float x = toPoint.x - fromPoint.x;
float y = toPoint.y - fromPoint.y;
return sqrt(x * x + y * y);
}
- (CGFloat)scaleAmount: (CGFloat)delta {
CGFloat pix = sqrt(self.frame.size.width * self.frame.size.height);
CGFloat scale = 1.0 + (delta / pix);
return scale;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if([timer isValid])
[timer invalidate];
moved = NO;
switch ([touches count]) {
case 1:
{
// single touch
UITouch * touch = [touches anyObject];
startTouchPosition = [touch locationInView:self];
initialDistance = -1;
break;
}
default:
{
// multi touch
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
initialDistance = [self distanceBetweenTwoPoints:[touch1 locationInView:self]
toPoint:[touch2 locationInView:self]];
break;
}
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
if([timer isValid])
[timer invalidate];
/*if ([touches count] == 1) {
CGPoint pos = [touch1 locationInView:self];
self.transform = CGAffineTransformTranslate(self.transform, pos.x - startTouchPosition.x, pos.y - startTouchPosition.y);
moved = YES;
return;
}****/
if ((initialDistance > 0) && ([touches count] > 1)) {
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
CGFloat currentDistance = [self distanceBetweenTwoPoints:[touch1 locationInView:self]
toPoint:[touch2 locationInView:self]];
CGFloat movement = currentDistance - initialDistance;
NSLog(#"Touch moved: %f", movement);
CGFloat scale = [self scaleAmount: movement];
self.transform = CGAffineTransformScale(self.transform, scale, scale);
// }
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
UITouch *touch1 = [[touches allObjects] objectAtIndex:0];
if ([touches count] == 1) {
// double tap to reset to default size
if ([touch1 tapCount] > 1) {
if (zoomed) {
self.transform = CGAffineTransformIdentity;
moved = NO;
zoomed = NO;
}
return;
}
}
else {
// multi-touch
UITouch *touch2 = [[touches allObjects] objectAtIndex:1];
CGFloat finalDistance = [self distanceBetweenTwoPoints:[touch1 locationInView:self]
toPoint:[touch2 locationInView:self]];
CGFloat movement = finalDistance - initialDistance;
NSLog(#"Final Distance: %f, movement=%f",finalDistance,movement);
if (movement != 0) {
CGFloat scale = [self scaleAmount: movement];
self.transform = CGAffineTransformScale(self.transform, scale, scale);
NSLog(#"Scaling: %f", scale);
zoomed = YES;
}
}
}
- (void)singleTap: (NSTimer*)theTimer {
// must override
}
- (void)animateSwipe: (int) direction {
// must override
}
It is not working fine on device. can anyone tell that where i am wrong.
When you use any CGAffinTransform.... the value of the frame property becomes undefined. In your code you are using the frame.size.width and frame.size.height to calculate the change in size. After the first iteration of CGAffinTransformScale you would not get the right scale factor. According to the documentation bounds would be the right property for scale calculations.