How to distinguish between Touch and drag in android... I want to create a listview in which people can drag and drop list items,that too with out using a handle...
What I have tried and failed is..
case MotionEvent.ACTION_DOWN:
mIsClickX = x;
mIsClickY = y;
and
case MotionEvent.ACTION_UP:
if(x == mIsClickX &&y == mIsClickY){
return super.onTouchEvent(ev);
}
Which doesn't work...
Thanks in advance for all your valuable suggestions
MotionEvent.ACTION_MOVE, you can also check:
1- http://www.zdnet.com/blog/burnette/how-to-use-multi-touch-in-android-2/1747
2- Android List View Drag and Drop sort
I think you can try this one.
A drag gesture starts when the first finger is pressed to the screen (ACTION_DOWN) and ends when it is removed (ACTION_UP or ACTION_POINTER_UP).
check this
Related
In Android what is the best way of providing unidirectional horizontal navigation? To set the expectation, I have started writing Android application two months ago.
In my situation, I have a list of screen size images which user will see one by one. To see the next image user has to swipe left (right-to-left motion). Once an image is seen user should NOT be able to go back, hence for this purpose right swipe (left-to-right motion) has to be disabled.
I have used a custom ViewPager to achieve this where I have overridden onTouchEvent method as below:
#Override
public boolean onTouchEvent(MotionEvent ev) {
boolean lockScroll = false;
switch (ev.getAction()) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_UP:
lastX = ev.getX();
return super.onTouchEvent(ev);
case MotionEvent.ACTION_MOVE:
if (lastX >= ev.getX()) {
lockScroll = false;
} else {
lockScroll = true;
}
lastX = ev.getX();
break;
}
if (lockScroll) {
return false;
} else {
return super.onTouchEvent(ev);
}
}
This works mostly. I mean almost always right swipes are blocked but in certain cases it happens which I am not able to figure out why.
Any clues, where might be the problem or is there any other way of handling this situation?
Thanks!
Welcome to Android development! One of the things you'll learn very quickly is never implement something that is already available open source. I recommend using the gallery function of https://github.com/nostra13/Android-Universal-Image-Loader, it will look a lot better and will be a lot more robust then if you or I made it ourselves.
Take a look at ViewPager#canScrollHorizontally. It's a prime candidate for overriding.
So, here's my problem: in my game I made a countdown at the start of the game, during which the user can't press the screen, so I wait until the countdown is over to enable the OnSceneTouchListener. As soon as it's enabled, the user will be able to do some stuff moving the finger (not important what).
The problem is that if the user starts moving the finger while there's the countdown, as soon as it's over the onSceneTouchEvent method starts getting inputs, but it skips the ACTION_DOWN event since the user is already moving the finger.
To prevent this I could of course use a boolean inside the onSceneTouchEvent method, but this way it would always check that for every single input. It doesn't influence much the performance, but I'd rather find another way if it's possible.
So I was thinking, is there a way in the AndEngine to obtain the touch input event (with the information of the coordinate pressed, that's what I really need), so that I could "force" the ACTION_DOWN event by simple doing what I should do with it in the method that makes the countdown?
Thanks in advance!
Here is an example, how you can get touch coordinates.
public boolean onTouchEvent(MotionEvent event) {
int myEventAction = event.getAction();
float X = event.getX();
float Y = event.getY();
switch (myEventAction) {
case MotionEvent.ACTION_DOWN:
break;
case MotionEvent.ACTION_MOVE: {
mySprite.setPosition(X, Y);
break;}
case MotionEvent.ACTION_UP:
break;
}
return true;
}
Source of this example
I'm currently developing an air-hockey simulation for android. For the multiplayer mode I'm tracking two touch events on the screen, which works well as long as the touch points don't get to close.
When the two fingers get to close, android only recognizes one touch event, in the middle of both points.
To make it even worse, android sometimes messes up the IDs after the collision.
I already thought about estimating the next touch points ans assigning IDs manually, does anybody know a better way, or knows about somebody who already fixed this problem programmatically?
NOTE: I'm testing on a Samsung Galaxy S 3
Not necessarily a logical fix to the issue, nevertheless a possible solution to the application:
If I'm not completely mistaken, air-hockey games shouldn't allow opponents to intrude on each others game field. If we assume a thick border cross the center of the screen (in portrait mode), then I wouldn't be allowed to do anything beyond that border, hence there is no point in tracking my finger after it reaches the border line.
Encapsulating your tracked touch events into valid physical locations as described might just help you in ignoring invalid points (given that the physical locations doesn't intersect, that is).
You might also have to keep track of direction of the touch vector: if the vector is stretching from the center of the screen towards "your end" it might be the opponents intruding finger or your own returning finger. In neither case should they affect the hockey puck (perhaps).
It may depend on the device you are using, but I'm using the code below in a Huawei X5 and It never mess up fingers, even if they touch each other or it I twist them over the screen.
private static PointF touchScreenStartPtArr[] = new PointF[10];
private static PointF touchScreenStopPtArr[] = new PointF[10];
private static PointF touchScreenCurrPtArr[] = new PointF[10];
OnTouchListener onTouchListenerMulti = new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction() & MotionEvent.ACTION_MASK;
int pointerIndex = (event.getAction() & MotionEvent.ACTION_POINTER_INDEX_MASK) >> MotionEvent.ACTION_POINTER_INDEX_SHIFT;
int fingerId = event.getPointerId(pointerIndex);
switch (action) {
case MotionEvent.ACTION_DOWN:
case MotionEvent.ACTION_POINTER_DOWN:
touchScreenStartPtArr[fingerId].x = event.getX(pointerIndex);
touchScreenStartPtArr[fingerId].y = event.getY(pointerIndex);
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_POINTER_UP:
case MotionEvent.ACTION_CANCEL:
touchScreenStopPtArr[fingerId].x = event.getX(pointerIndex);
touchScreenStopPtArr[fingerId].y = event.getX(pointerIndex);
break;
case MotionEvent.ACTION_MOVE:
int pointerCount = event.getPointerCount();
for (int i = 0; i < pointerCount; i++) {
touchScreenCurrPtArr[fingerId].x = event.getX(i);
touchScreenCurrPtArr[fingerId].y = event.getY(i);
}
break;
}
return true;
}
};
Note that I'm using fingerId and not pointerId to identify the correct finger, as pointer id may change when one finger is released.
Hope it works for you.
Here's the way I see it.
The touchscreen hardware gives you a resolution below which two touches are the same as one. This is something you cannot change.
Now the question is, what to do when two touches merge? (This is something that can be tested for programmatically one would think; e.g. if 2 touch pts -> 1 touch pt. AND prev touch pt 1 is close enough to prev touch pt 2...). In your case, I would move both pucks along the merged touch gesture until they separate, then return individual control.
Of course, I see several problems with this, like which touch controls which puck after the split? Maybe one person lifted their finger during the merge.
You could have both players lose control of their puck if a merge occurs. This could simulate the shock to the wrist as your hand bashes into your opponent's :)
I also like #dbm idea.
Hope this helps. Probably didn't :)
I write a very simple android application, that I can draw something on the pad. Touch the screen with a finger, you will see a green ball, move your finger, you will see a red line.
But I found a very strange thing: If I touch the screen with two fingers one by one very fast, it will draw a line between them! (Imaging you are pressing two keys jkjkjkjkjkjjkjkjkjkjkjkj on the keyboard)
The key code is pretty simple:
public boolean onTouch(View v, MotionEvent event) {
int action = event.getAction();
switch (action & MotionEvent.ACTION_MASK) {
case MotionEvent.ACTION_DOWN:
multiTouch = false;
id = event.getPointerId(0);
PointF p = getPoint(event, 0);
path = new Path();
path.moveTo(p.x, p.y);
paths.add(path);
points.add(copy(p));
break;
case MotionEvent.ACTION_POINTER_DOWN:
multiTouch = true;
for (int i = 0; i < event.getPointerCount(); i++) {
int tId = event.getPointerId(i);
if (tId != id) {
points.add(getPoint(event, i));
}
}
break;
case MotionEvent.ACTION_MOVE:
if (!multiTouch) {
p = getPoint(event, 0);
path.lineTo(p.x, p.y);
}
break;
}
invalidate();
return true;
}
The full source is here: https://github.com/freewind/TouchTest/blob/master/src/com/example/MyImageView.java
And it's a working demo: https://github.com/freewind/TouchTest
Or you can just download the signed apk on your android device, and test it yourself: https://github.com/freewind/TouchTest/blob/master/TouchTest.apk?raw=true
You can see in my code, I have checked if it's multi touch and disabled drawing on that case.
My android version is 4.0, and my code target is 2.3.3
There is a picture on my android pad:
You can see there are some lines but it should not be, there should be a green ball on the left of the red line instead.
I'm not sure why android treat fast single touch as moving, I considered 3 reasons:
My code has something wrong
Android sdk has something wrong
My android pad has something wrong, e.g. missing a ACTION_DOWN event
How to find out the real reason?
UPDATE
One of my friend used his android mobile(android 2.1) to test this app and found there is no red line, another used android 2.3.5 and found there are red lines.
Please review my code, I have checked multi-touch by ACTION_POINTER_DOWN, and will do nothing on ACTION_MOVE if there are more than 1 points. So the id of point is not needed. (Actually, in my first version of this code, I used id but have the same issue).
And I don't think this is an expected behavior, because it made the development of touching programs hard. I found this issue because in my another application(user can drag/zoom/rotate an image by fingers), the image sometimes "jump" on screen.
I even tried a popular game (Fruit Ninja) on my android pad and iTouch, and found android version has the issue but iTouch doesn't.
Now I'm sure there is something wrong (missing an ACTION_UP event when the first finger ups), but I still don't know what causes it. My android pad? Or Android sdk?
That is way it works for multitouch. When you press fast android handle it as gesture, and you will have 2 pressed pointers. To avoid it try to handle action_up, or use action_pointer_down instead
you can check the id of the touch , so that you will handle only the first touch alone.
alternatively , you can monitor all touches and handle them together .
I have an activity filled with buttons on the screen,and each has characteer text
something like : [A] [B] [C] etc. I need to code that when the user touches and slides his/her finger on the screen, it should aggregate the text of each touched button ,sample result should be : A + B + C = ABC . I have written some code but it does not work as intended . in my code ,I keep the array of buttons called buttons to identify which button is touched at that moment , but this code just work for first touch , it is Action_Down , it realize just first button which I touch , When I slide my finger around I cannot get other buttons texts. , So what is your suggestions ? help please . .
public boolean onTouch(View v, MotionEvent event) {
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
for(int i=0;i<buttons.size();i++){
if(buttons.elementAt(i).getId()==v.getId()){
text+=buttons.elementAt(i).getText();
break;
}
}
break;
case MotionEvent.ACTION_MOVE:
for(int i=0;i<buttons.size();i++){
if(buttons.elementAt(i).getId()==v.getId()){
text+=buttons.elementAt(i).getText();
break;
}
}
case MotionEvent.ACTION_UP:
Toast.makeText(context,text,Toast.LENGTH_SHORT).show();
text="";
break;
}
return false;
}
I guess you think of multi touch, but your code is not.
For multi touch you need to use ACTION_POINTER_UP/DOWN. But not all devices support multi touch.
For non-multi-touch you need a more complex handling. Buttons may be selected. The join must be done explicitly.