Reputation: 285
I have two custom uibuttons.
@interface myButton : UIButton
I overwrite several methods like
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
// do something
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesMoved:touches withEvent:event];
[self.nextResponder touchesMoved:touches withEvent:event];
UITouch *touch = [touches anyObject];
CGPoint touchPoint = [touch locationInView:self];
if (!CGRectContainsPoint(self.bounds, touchPoint)) {
[self touchesCancelled:touches withEvent:event];
}
return;
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
// do something
}
-(void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
[super touchesCancelled:touches withEvent:event];
return;
}
The thing I want is , when I touch a button, I can keep moving my touch to another button. I tired to call touchesCancelled when the touch is out of the bound of the first button I touched. So I "think" then I move to another button it will be a new touch event. But it doesn't work like this.
Did I do something wrong? Or the touchesCancelled method is not used for like this? Thanks in advance!
Upvotes: 1
Views: 2377
Reputation: 4628
Your suspesions are correct, this is not how touchesCancelled:withEvent:
was intended to be used. From the documentation:
This method is invoked when the Cocoa Touch framework receives a system interruption requiring cancellation of the touch event; for this, it generates a UITouch object with a phase of UITouchPhaseCancel. The interruption is something that might cause the application to be no longer active or the view to be removed from the window.
Your responder will receive the touches cancelled event if your user receives an incoming phone call, SMS or their alarm goes off etc. It should be used to clean up any state information that was established in the other touch events.
It seems as though you want to change the responder associated with the touch events mid-touch i.e. when you drag the touch from the bounds of the first button and enter that of the second button it should become the responder recieving the touch events. Unfortunately that is not the way responders are designed to work. Once a UIView
is identified as being the responder, as returned in hitTest:withEvent:
, this will be the UIView
to receive touch events.
A possible workout to achieve what you want would be to handle the touch events (touchesBegan:withEvent:
, touchesMoved:withEvent:
etc.) in a superview that contains both of your buttons. Then your superview will receive the touch events and you can take action depending on which button's frame you are within:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
{
CGPoint touchLocation = [touch locationInView:self.view];
UIButton *button;
if (CGRectContainsPoint(self.button1.frame, touchLocation))
{
button = self.button1;
NSLog(@"touchesMoved: First Button");
}
else if (CGRectContainsPoint(self.button2.frame, touchLocation))
{
button = self.button2;
NSLog(@"touchesMoved: Second Button");
}
// Do something with button...
}
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
{
CGPoint touchLocation = [touch locationInView:self.view];
UIButton *button;
if (CGRectContainsPoint(self.button1.frame, touchLocation))
{
button = self.button1;
NSLog(@"touchesMoved: First Button");
}
else if (CGRectContainsPoint(self.button2.frame, touchLocation))
{
button = self.button2;
NSLog(@"touchesMoved: Second Button");
}
// Do something with button...
}
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
for (UITouch *touch in touches)
{
CGPoint touchLocation = [touch locationInView:self.view];
UIButton *button;
if (CGRectContainsPoint(self.button1.frame, touchLocation))
{
button = self.button1;
NSLog(@"touchesEnded: First Button");
}
else if (CGRectContainsPoint(self.button2.frame, touchLocation))
{
button = self.button2;
NSLog(@"touchesEnded: Second Button");
}
// Do something with button...
}
}
Upvotes: 2