I am unable to figure out why the ACTION_UP event is not being fired when I move my finger away from contact in the following code.
public boolean onTouch(View v, MotionEvent event) {
switch(event.getActionIndex()){
case MotionEvent.ACTION_UP:
Utils.log("Touch Up");
break;
case MotionEvent.ACTION_DOWN:
Utils.log("Touch Down");
break;
}
return true;
}
You should use getActionMasked().
getAction() returns single pointer events (and deprecated multiple pointer events...)
getActionMasked() returns single and multiple pointer events (use with getActionIndex() to determine which pointer),
getActionIndex() returns only the pointer index.
So getActionIndex() returns which finger performed a down / up action (0, 1, 2, etc.) While getAction() or getActionMasked() return the single pointer events you want (ACTION_DOWN, ACTION_UP, etc.)
Replace your code with mine.
public boolean onTouch(View v, MotionEvent event) {
//Here's the problem
switch(event.getAction()){
case MotionEvent.ACTION_UP:
Utils.log("Touch Up");
break;
case MotionEvent.ACTION_DOWN:
Utils.log("Touch Down");
break;
}
return true;
}
For others having a similar problem, one of the reasons why ACTION_UP is not fired could be overly sensitive ACTION_MOVE. In this case, ACTION_UP never gets fired because system interprets touch action as ACTION_MOVE and fires it instead.
A solution for that is to check when ACTION_MOVE happens if x and y offset is big enough to handle it as ACTION_MOVE, otherwise, you can threat it as ACTION_UP.
Here is SO example.
Related
I want to create a dual side swipe button which gives haptic feedback on reaching the end. The image is attached.
https://i.stack.imgur.com/eIECf.png
This is not a question with a simple answer, but ill try to give you a general direction on how to go about implementing something like this:
You need handle Touch events on your button, yourself.
something like:
button.setOnTouchListener(new OnTouchListener()
{
#Override
public boolean onTouch(View arg0, MotionEvent arg1)
{
switch(event.getAction()) {
case MotionEvent.ACTION_DOWN:
// touch down code
break;
case MotionEvent.ACTION_MOVE:
// touch move code
break;
case MotionEvent.ACTION_UP:
// touch up code
break;
}
return false;
}
});
In onTouch, you need to do two things:
Move the button to the appropriate location, base on the motion of the user's finger.
for this, you should probably store the position of ACTION_DOWN, and then calculate relative movement in ACTION_MOVE and move your button to match it.
If you want your button to only move along some axis, you need to calculate the appropriate position on this axis, yourself.
in ACTION_UP, check the position of your button, and if its close enough to where you want your swipe to end, execute the action
i am creating an android game and have an onTouchEvent like this:
#Override
public boolean onTouchEvent(MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
if (!action) {
action = true;
}
} else {
action=false;
}
return true;
}
My problen is now, that action is false as soon as i swipe my finger a little bit.
thanks for helping,
Florian
If you want to return true even when a swipe input occurs, you could store the last action to compare if the last action was ACTION_DOWN and if the current 'event.getAction()' is also ACTION_DOWN, then you can assume that the swipe action occurs (also if the previous 'x' and 'y' positions differ to the current 'x' and 'y' positions), therefore still return true. Any other scenario, you can return false.
You could also try looking in the android API documentation about a swipe input action/gesture.
Hope that is helpful.
So I have spent a long time looking to see if there is a solution for this. Basically, the below code allows me to press on a button, when I press (action_down) the 'pressed version' of the button is displaying good, then when I remove my finger the graphic returns to normal (action_up).
This part is working good BUT I need the ACTION_DOWN to stay active a little longer after the user presses the button and not return to ACTION_UP so fast. I can see lots of different people asking this question but no answers relating to editing the action_up or action_down part. I thought there must be some simple way to achieve this goal..
The current code:
#Override
public boolean onTouch(View v, MotionEvent event) {
if (MotionEvent.ACTION_DOWN == event.getAction()) {
int img = Integer.parseInt(v.getTag(R.id.tag_press_down_img).toString());
if (v instanceof ImageView) {
((ImageView) v).setImageResource(img);
}
} else if (MotionEvent.ACTION_UP == event.getAction()) {
int img = Integer.parseInt(v.getTag(R.id.tag_press_up_img).toString());
if (v instanceof ImageView) {
((ImageView) v).setImageResource(img);
}
}
return false;
}
(This code is working fine but the user experience is bad because the button reverts back to ACTION_UP too fast (immediately) after being released - I would like ACTION_DOWN to 1) display for 1-2 seconds then revert back to ACTION_UP OR 2) remain in action_down until the called event is complete - in this case loading another screen).
Thank you!
I am make a application on android that need multi-touch gesture! I found that my devices Novo 7 (ainol) supports 5 touch points. I implement onTouch for a View like this
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_DOWN || event.getAction() == MotionEvent.ACTION_DOWN){
Log.i("Touch", "Touch "+event.getPointerCount() + " -- Position " +
event.getRawX()+","+event.getRawY());
}
else if ((event.getAction() & MotionEvent.ACTION_MASK) == MotionEvent.ACTION_POINTER_UP|| event.getAction() == MotionEvent.ACTION_UP){
Log.i("Touch up","Pointer = "+event.getPointerCount());
}
return true;
}
At first, everything is ok, the log is printed out perfectly with 5 message. But things happened when i touch and release the 6th point on screen. The log re-printed out 5 message. Can you tell me what is going on here. Sorry for my bad english and if this is a noob question! Thank you very much!
----------- EDITED--------------------
After logging for ACTION_POINTER_UP and ACTION_UP, i found out that when the 6th finger touch (touch down) the screen, all the current pointers (5 pointers) is release from the Event (e.g the action_up and action_pointer_up is call on 5 previous pointers)! Now, the question is, how the android process this situation when the limitation of touch point is reach.
This is a fairly simple question I am sure, but I can't seem to figure out a way around this little thing. First, here is my code:
switch (event.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
Log.w("Platformer", "primary down");
break;
case MotionEvent.ACTION_UP:
Log.w("Platformer", "primary up");
break;
case MotionEvent.ACTION_POINTER_1_DOWN:
Log.w("Platformer", "secondary down");
break;
case MotionEvent.ACTION_POINTER_1_UP:
Log.w("Platformer", "secondary up");
break;
}
All I wanted it to do was when I pressed down, it would show me in the log whether the primary or secondary pointer was down, and when I release, do the same thing. The problem is, it always works on the down, but on up, whatever the 1st finger that comes up is, regardless of if it was the primary or secondary pointer originally, it returns that the secondary pointer was removed. Any idea around this? I am guessing it is something simple, but I don't know where to look truthfully. Thanks in advance.
WWaldo
ACTION_UP means that the gesture is over, that is, all pointers are up.
ACTION_POINTER_UP means that a non-primary pointer is up, you'll have to check the event to figure out which, i.e.:
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >>
MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int pointerId = event.getPointerId(pointerIndex)
ACTION_POINTER_1_UP and ACTION_POINTER_2_UP are deprecated now.
You should note that this is extremely buggy on Android versions less than Gingerbread. I find that if I lift the first of two touches and place it back down, the pointers swap index and ID. Very frustrating.
Use getPointerId to get which pointer is being selected.
Edit
To answer the question in the comment, try:
for (int i = 0; i < ev.getPointerCount(); i++) {
switch (ev.getAction() & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
Log.d(TAG,"down "+ ev.getPointerId(i));
break;
case MotionEvent.ACTION_MOVE:
Log.d(TAG,"move "+ ev.getPointerId(i));
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
Log.d(TAG,"up "+ ev.getPointerId(i));
break;
}
}