Lets say I wan\'t to add 1 to an integer. This will only be done when I push down on a UIButton
and then release my finger on another UIButton
.
Another approach is to use a UITapGestureRecognizer
and UIPanGestureRecognizer
and track the location in your buttons. I found this to be more readable. (I actually ended up using UILabels because I didn't need any further UIButton
behavior.)
Try implementing the button you wish to touch down on as a "Touch Down", "Touch Up Inside", and "Touch Up Outside" button.
UIButtons can respond to many differing types of events Touch Cancel Touch Down Touch Down Repeat Touch Drag Enter Touch Drag Exit Touch Drag Inside Touch Drag Outside Touch Up Inside Touch Up Outside
You can implement different action code for each of these for each button for best control of whatever you wish. The simplistic case only uses the 2 I mentioned above.
THIS CODE HAS BEEN TESTED AND DOES WORK
In your ViewController header file (here was mine):
@interface ViewController : UIViewController{
IBOutlet UIButton * upButton; // count up when finger released button
IBOutlet UIButton * downButton;
IBOutlet UILable * score;
BOOL isButtonDown;
unsigned int youCounter;
}
-(IBAction)downButtonDown:(id)sender;
-(IBAction)downButtonUpInside:(id)sender;
-(IBAction)downButtonDragOutside:(id)sender event:(UIEvent *)event;
-(IBAction)downButtonUpOutside:(id)sender event:(UIEvent *)event;
@end
In your .xib, connect the down button (the one you wish to be your original finger pressed button) to the proper actions above.
In your ViewController.m file
-(void)viewDidLoad{
[super viewDidLoad];
isButtonDown = NO;
youCounter = 0;
}
-(IBAction)downButtonDown:(id)sender{
isButtonDown = YES;
}
-(IBAction)downButtonUpInside:(id)sender{
isButtonDown = NO;
}
-(IBAction)downButtonDragOutside:(id)sender event:(UIEvent *)event{
NSArray theTouches = [[event allTouches] allObjects];
[downButton setHighlighted:YES];
if(YES == [upButton pointInside:[[theTouches objectAtIndex:0] locationInView:upButton] withEvent:event]){
[upButton setHighlighted:YES];
}else{
[upButton setHighlighted:NO];
}
}
-(IBAction)downButtonUpOutside:(id)sender event:(UIEvent *)event{
if(YES == [upButton pointInside:[[theTouches objectAtIndex:0] locationInView:upButton] withEvent:event]){
youCounter++;
score.text = [NSString stringWithFormat:@"Score = %d", youCounter];
}
[downButton setHighlighted:NO];
[upButton setHighlighted:NO];
}
// Create a button, add targets
UIButton *cloudButton = [UIButton buttonWithType:UIButtonTypeCustom];
[cloudButton setImage:[UIImage imageNamed:@"notification_add.png"] forState:UIControlStateNormal];
[cloudButton setFrame:CGRectMake(0, 0, 30, 30)];
[cloudButton addTarget:self action:@selector(dragBegan:withEvent: )
forControlEvents: UIControlEventTouchDown];
[cloudButton addTarget:self action:@selector(dragMoving:withEvent: )
forControlEvents: UIControlEventTouchDragInside | UIControlEventTouchDragOutside];
[cloudButton addTarget:self action:@selector(dragEnded:withEvent: )
forControlEvents: UIControlEventTouchUpInside |
UIControlEventTouchUpOutside];
[self.view addSubview:cloudButton];
//event methods
- (void) dragBegan: (UIControl *) c withEvent:ev
{
NSLog(@"dragBegan......");
}
- (void) dragMoving: (UIControl *) c withEvent:ev
{
NSLog(@"dragMoving..............");
}
- (void) dragEnded: (UIControl *) c withEvent:ev
{
NSLog(@"dragEnded..............");
}
Do the following for the first UIButton in the ViewDidLoad
method
[button1 addTarget:self action:@selector(dragMoving:withEvent: )
forControlEvents: UIControlEventTouchDragInside | UIControlEventTouchDragOutside];
[button1 addTarget:self action:@selector(dragEnded:withEvent: )
forControlEvents: UIControlEventTouchUpInside |
UIControlEventTouchUpOutside];
In the dragMoving
method
- (void)dragMoving:(UIControl *)c withEvent:event{
NSSet* touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:[button2 superview]];
if ( CGRectContainsPoint(button2.frame, currentPoint) ) {
NSLog(@"over second button);
}
}
As for the dragEnded
method:
- (void) dragEnded:(UIControl *)c withEvent:event{
NSSet* touches = [event allTouches];
UITouch *touch = [touches anyObject];
CGPoint currentPoint = [touch locationInView:[self.button1 superview]];
if ( CGRectContainsPoint(button2.frame, currentPoint) ) {
NSLog(@"ended on button 2");
//add 1 to the integer
}
else {
NSLog(@"not on button 2");
}
}
//Initalize a BOOL variable to know if you started the touch in the right place.
BOOL correctStart = NO;
//Get the location of the first touch, if its in the first button make correctStart = YES.
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
for (UITouch *touch in allTouches) {
if ([touch locationInView:button1.view]) {
correctStart = YES;
}
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSSet *allTouches = [event allTouches];
for (UITouch *touch in allTouches) {
if (([touch locationInView:button2.view]) && (correctStart == YES)) {
anInteger++;
}
}
correctStart = NO;
}
I did not try this code as I am not at my mac, so your results may vary, but this should get you going in the right direction.