fljot / Gestouch

Gestouch: multitouch gesture recognition library for Flash (ActionScript) development.
MIT License
356 stars 84 forks source link

swipe container and tap with button scaling up #85

Closed harry90 closed 9 years ago

harry90 commented 9 years ago

Hello, I have a button container which can be swiped and tapped. Each button in the container should be scaled up when it is pressed and scale back down when released. I tried to do this with tapGesture, but there is no GESTURE_BEGAN and GESTURE_ENDED event.

Then I tried to do it with LongPressGesture, but there the button scale up reacts too slow, even when minPressDuration is set to zero. Now I found out that there is a GESTURE_POSSIBLE event fired, I think the problem is with the swipe of the button container combined.

Could you please help me, how to handle this?

Here is my code

var swipeCont:SwipeGesture = new SwipeGesture(contBtns);

// for each button var tapBtn:LongPressGesture = new LongPressGesture(button1); tapBtn.minPressDuration = 0; tapBtn.addEventListener(GestureEvent.GESTURE_BEGAN, scaleBtnUp); tapBtn.addEventListener(GestureEvent.GESTURE_ENDED, scaleBtnDown);

tapBtn.requireGestureTo Fail(swipeCont);

fljot commented 9 years ago

Yeah, LongPressGesture delays in ur case because of tapBtn.requireGestureTo Fail(swipeCont);.

How can I help you? What do you want to achieve?

harry90 commented 9 years ago

Ok, I want the buttons to scaleUp when the Press/Tap begins and to scale down when the Press/Tap ends, like the typical button effect "scaleWhenDown".

I tried it simple with TapGesture and SwipeGesture and uses the scaleWhenDown button property in Starling, but the problem then is that the button scales up when the button container is swiped. The button should only scale up when it it tapped and when the container is swiped teh scaleX/scaleY should not change.

Do you understand?

fljot commented 9 years ago

Yeah, I got that part, you could have it with LongPressGesture as you wrote(*). You don't like the delay? Well, maybe remove requireGestureToFail then? But this way swipe will fail as soon as long press is recognized (instantly if you set minPressDuration = 0), which means you have to allow simultaneous recognition. Is that your desired UX? I was asking you "what do you want to achieve" in UX sense, from the user point of view, not technically.

(*): even though I'd say this is not the best use of LongPressGesture since you're basically not interested in detecting long press. You could extend TapGesture and dispatch TouchEvent.TOUCH_BEGIN for example when it starts to track first finger so that you could scale button up. And GestureEvent.GESTURE_RECOGNIZED and GESTURE_FAILED to scale back down.

harry90 commented 9 years ago

Yes using LongPressGesture is only because there is no GESTURE_BEGAN and GESTURE_ENDED event for TapGesture. Extending TapGesture is a good idea. But I think it would be better to use GESTURE_RECOGNIZED for the scale up and TOUCH_ENDED for the scale down, because it is possible that a user taps on the button and while pressing it, he wants to start the swipe, so if it is really a tap is not clear till the button is released. If a user decides to make a swipe while he presses the button, how can I switch from the recognized tap to execute the swipe?

And what I don't know how to code: "You could extend TapGesture and dispatch TouchEvent.TOUCH_BEGIN for example when it starts to track first finger so that you could scale button up" ? Should a Eventlistener Gestouch Gesture and Starling Touch added combined or is anything else to do for extending?

fljot commented 9 years ago

You say "but I think it would be better to use ...", but you don't really explain how it's better and end up with a question =))

If a user decides to make a swipe while he presses the button, how can I switch from the recognized tap to execute the swipe? What do you mean by "switch" (this is a question you should ask yourself really).

Problem 1: ensure swipe can be recognized. For simultaneous recognition check Apple's documentation/videos, gesturesShouldRecognizeSimultaneouslyCallback will help you (or canPreventGesture or canBePreventedByGesture in case u're gonna extend something).

Problem 2: scale down when swipe is recognized. If you play by the rules (of logic) and don't try cut the corners with inappropriate use of gestures (LongPressGesture here), then you get all the benefits. If you use TapGesture (because you're interested in tap, which is about touch releasing), then it would be automatically failed once swipe is recognized, Dispatch something from the extended TapGesture:

override protected function onTouchBegin(touch:Touch):void
{
    if (touchesCount == 1) dispatch some event to trigger your scaling up
    super.onTouchBegin(touch);
}

TapGesture will still be in POSSIBLE state, which means it can be automatically aborted by swipe.

harry90 commented 9 years ago

Ok now I understand the logic behind it better and I found a solution that works not bad. I use TapGesture and tapBtn.requireGestureTo Fail(swipeCont). On the SwipeGesture GESTURE_POSSIBLE I add a DelayCall of 0.1 sec to Starling.juggler, when this is called the button scales up. The DelayCall prevents the button scaling up when the user does a quick swipe with his finger. On SwipeGesture GESTURE_RECOGNIZED if the DelayCall is implemented, the DelayCall is removed and nulled. The swipe is dispatched and the button scales down. On TapGesture GESTURE_RECOGNIZED if the DelayCall is implemented, the DelayCall is removed and nulled. The button scales down and the tap is dispatched. On TapGesture GESTURE_FAILED if the DelayCall is implemented, the DelayCall is removed and nulled. The button scales down. Do you see problems with this solution?

fljot commented 9 years ago

On the SwipeGesture GESTURE_POSSIBLE I add a DelayCall

Yeah, I see problem – I don't see how this could happen. Gesture doesn't inform with GESTURE_POSSIBLE at the beginning of interaction (because it's most of the time in that possible state already). I see already, that I should probably add some event for this – could be handy.

Also, why do you try to connect wrong things together?)) Button scaling is primarily related to touching-tapping. Writing logic based on swipe gesture seems kinda smelly. Imagine you wouldn't have swiping functionality at all. In this case your scaling functionality would have to look totally different. That doesn't seem right.

Also, just to understand other things right, do you have swipe for container or each button?

harry90 commented 9 years ago

Right, I use GESTURE_POSSIBLE because I noticed that this event fires at the beginning of the touch. Ok then I have to add GESTURE_FAILED with scale down to the swipe. I will observe if the scale up will happen unexpected, but for the moment it works. But would be great if there is a GESTURE_BEGAN for TapGesture..

The SwipeGesture is only for the container. Yes, it would be cleaner if DelayCall on GESTURE_POSSIBLE is with TapGesture, but then each button needs that EventListener, adding the EL to the SwipeGesture is only once for the container - so less EL are needed. Without swipe you could simply use the "scaleWhenDown" property of the Starling button class. I'm surprised what great effort is necessary to get that simple scale effect :)

fljot commented 9 years ago

Right, I use GESTURE_POSSIBLE because I noticed that this event fires at the beginning of the touch.

That's surprising. Are you sure?

TapGesture can't have GESTURE_BEGAN, as it's not continuous gesture.

harry90 commented 9 years ago

It seemed logical to me that GESTURE_POSSIBLE occurs before GESTURE_RECOGNIZED, but if you say GESTURE_POSSIBLE could fire unexpected my solution is not the best.

Would be great if you could tell me the steps how to do it right, I know you already told me some points but didn't get it, sorry I'm not that experienced in coding..

fljot commented 9 years ago

So what can I make more clear from what I told already? Because I basically told everything...

harry90 commented 9 years ago

Ok I use swipeCont.canPreventGesture(tapBtn).

Dispatch something from the extended TapGesture:

override protected function onTouchBegin(touch:Touch):void { if (touchesCount == 1) dispatch some event to trigger your scaling up super.onTouchBegin(touch); }

  • Where do I have to put this code?
  • What means "dispatch some event to trigger your scaling up"? Can you make an example for that.
  • How is scaling down handled?
fljot commented 9 years ago

Man, I understand that you want to get things work, but you kinda have to put some effort, right? In readme I specifically mentioned that this lib is similar by API and functionality to Apple's UIGestureRecognizers and that there are high-quality videos and documentation! It's clearly explained there what is canPreventGesture() used for (in short: it's not meant to be used like that). And I even put it under special namespace so that people won't use it directly. Read docs, watch videos, see my examples or check the source code – every possible thing is there, just take it.

harry90 commented 9 years ago

Ok thanks, now I understand how to code it and scaling up with the override works. But when testing sometimes there is a flickering on the button when a user makes a quick touch movement for swiping (flickering means button is scaling up).

fljot commented 9 years ago

Yeah, that's because swipe is recognized a bit later after scaling starts (immediately as you touch the button, I suppose). That's up to you to decide how to handle that, it's the matter of UI/UX planning, not purely "coding problem".

harry90 commented 9 years ago

Well, it would work with adding a delay call at onTouchBegin, as I described above? What about that?

fljot commented 9 years ago

I guess

harry90 commented 9 years ago

Ok, I see, great lib anyway, thanks a lot for help !!

fljot commented 9 years ago

Welcome)