Detecting Swipes on top of Buttons

Discussion in 'iOS Development' started by cwe7976, Jun 5, 2009.

  1. cwe7976

    cwe7976 New Member

    Joined:
    Oct 4, 2007
    Messages:
    10
    Likes Received:
    0
    I have a few buttons placed right on self:

    [b_one setTitle

    Please Register or Log in to view images

    "B1" forState:UIControlStateNormal];
    [b_one addTarget:self action

    Please Register or Log in to view images

    selector(onePressed) forControlEvents:UIControlEventTouchUpInside];

    [b_two setTitle

    Please Register or Log in to view images

    "B2" forState:UIControlStateNormal];
    [b_two addTarget:self action

    Please Register or Log in to view images

    selector(twoPressed) forControlEvents:UIControlEventTouchUpInside];


    And have set up a working swipe detector using:
    - (void)touchesBegan: (NSSet *)touches withEvent: (UIEvent *)event
    {
    UITouch *touch = [touches anyObject];
    touchStart = [touch locationInView:self.view];
    }

    - (void)touchesMoved: (NSSet *)touches withEvent: (UIEvent *)event
    {
    UITouch *touch = [touches anyObject];
    CGPoint currentPosition = [touch locationInView:self.view];

    CGFloat deltaX = fabsf(touchStart.x - currentPosition.x);
    CGFloat deltaY = fabsf(touchStart.y - currentPosition.y);

    if (deltaX >= MinimumGestureLength && deltaY <= MaximumVariance)
    { .... }
    }

    The swipes are detected when starting not on the buttons, but when I swipe starting on the button it is undetected.

    How do I get swipes to work no matter where they originate/end?
  2. Pelaez-1

    Pelaez-1 New Member

    Joined:
    May 5, 2008
    Messages:
    822
    Likes Received:
    0
    Device:
    iPhone
    I'm haven't implemented anything like that yet, but here's what I THINK might be happening:
    When you touch the buttons, you are not touching the view, but one of it's subviews, so you have to check if the touch in the view was detected or not. If it wasn't, check if it was detected in the subviews.

    Again, I don't promise it's going to work because I haven't worked with touch events yet.

    Code:
    touchStart = [touch locationInView:self.view];
    if(touchStart == nil){
      NSArray *tempArray = [self.view subviews];
      for(int i=0; i < [tempArray count]; i++){
        touchStart = [touch locationInView:[tempArray objectAtIndex:i]]
        if(touchStart != nil){
          touchStart = CGPointMake(touchStart.x + [tempArray objectAtIndex:i].bounds.x, touchStart.y + [tempArray objectAtIndex:i].bounds.y);
          break;
        }
       
      }
      [tempArray release];
    }
  3. cwe7976

    cwe7976 New Member

    Joined:
    Oct 4, 2007
    Messages:
    10
    Likes Received:
    0
    Hey Pelaez,

    Thanks for the help, but the code above can't pass compilation:

    it says I: can't compare (touchStart == nil)
    and: [tempArray objectAtIndex:i].bounds.x "request for member 'bounds' in something that is not a structure or union"
  4. SkylarEC

    SkylarEC Super Moderator Emeritus Staff Member

    Joined:
    Sep 19, 2007
    Messages:
    6,642
    Likes Received:
    129
    UIButtons have their own touch recognition methods. That's how they detect button presses. You will need to subclass them to both do what they do and pass along the touch events.

    Also, your swipe detection fails to figure out the direction of the swipe.
  5. cwe7976

    cwe7976 New Member

    Joined:
    Oct 4, 2007
    Messages:
    10
    Likes Received:
    0
    its a dirty way to do it, but it works...

    I disabled all the buttons:
    [b_one setEnabled:false];
    [b_two setEnabled:false];

    The issue I figured out is the: [touchStart locationInView:self.view] wasnt picking up on buttons, so instead I iterate through each subview (all buttons) until locationInView spits out a non zero value. Set a trigger in touchesBegan if a button was touched and if the trigger isnt changed by a swipe motion, then assume that the release was in the button as well
    Code:
    - (void)touchesBegan: (NSSet *)touches withEvent: (UIEvent *)event {
    	
    UITouch *touch = [touches anyObject];
    	NSArray *tempArray = [self.view subviews];
    	for (int i = 0; i < [tempArray count]; i++)
    	{
    		touchStart = [touch locationInView:[tempArray objectAtIndex:i]];
    		CGRect buttonBounds = [[tempArray objectAtIndex:i] bounds];
    		if (CGRectContainsPoint(buttonBounds, touchStart))
    		{
    			holderButton = [tempArray objectAtIndex:i];
    		}
    	}
    	touchStart = [touch locationInView:self.view];
    	trigger = true;
    	
    }
    -(void)touchesEnded: (NSSet*)touches withEvent: (UIEvent *)event
    {
    	if (trigger == true)
    		[self buttonHit:holderButton];
    }
    - (void)touchesMoved: (NSSet *)touches withEvent: (UIEvent *)event {
    	UITouch *touch = [touches anyObject];
    	CGPoint currentPosition = [touch locationInView:self.view];
    	
    	CGFloat deltaX = fabsf(touchStart.x - currentPosition.x);
    	CGFloat deltaY = fabsf(touchStart.y - currentPosition.y);
    	
    	//means a swipe was detected
    	if (deltaX >= kMinimumGestureLength && deltaY <= kMaximumVariance) 
    	{
    		trigger = false;
    	}
    }
    -(void)buttonHit: (UIButton*)pickedMe
    {
    	if (pickedMe == b_one)
    		...do whatever...
    	if (pickedMe == b_two)
    		...do whatever...
    }
    
  6. zhwtz12345

    zhwtz12345 New Member

    Joined:
    Jun 28, 2010
    Messages:
    1
    Likes Received:
    0
    reply above

    the way of running through all the subviews would let you lose the multi-touch capability. For example, you can only touch one button at the same time now@ Is there a way still could let multitouch working and detect multi swipe?

    Tony

Share This Page