Supporting unidirectional swipe in Android widgets - android

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.

Related

Is there a offset between onTouchEvent and onTouchListener?

I have developed a game that shoots when player touches the screen by using onTouchListener for my custom SurfaceView and Thread.
But now I want to change the approach and instead of onTouchListener I added onTouchEvent to the SurfaceView o my Activity.
The problem is that I get some kind of offset when I click on the emulator.
Everything is working great, except that offset keeps appearing and I don't understand why.
Also let me mention that my app is running in landscape mode, maybe this is relevant.
I suspect that it isn't working properly because onTouchListener was added to the view and depended on it, but onTouchEvent doesn't depend on the view.
Also my view doesn't have any padding or margin properties, it is full-screen view (fill_parent).
Does anyone have any ideas on this?
I have done my application, and everything works correctly now, but i still do not know what the problem was.
After lots of debugging of my application the onTouchEvent returned random Y values that were always higher than the ones that the onTouchListener returned. And i am not sure why this is hapening since my view that recognizes the onTouchListener is a full-screen view.
So i figured out a way to get passed this by doing some math.
The first function that the android calls is the onTouch method which gives the correct values but just for one touch. I needed it to give right values even on the MotionEvent.ACTION_MOVE so i noticed that MotionEvent.ACTION_MOVE is actually doing correctly depending on the first touch recognized by the onTouchEvent.
So i just got the coordinate Y from the onTouch and the different coordinate with the offset from onTouchEvent calculated the difference and in every onTouchEvent from there, until the user lifts up their finger, i just subtract that difference and that gives me the correct value.
If anyone else has this problem, and doesn't know how to fix it, here is my code, maybe it will be helpful.
#Override
public boolean onTouchEvent(MotionEvent arg1) {
/*you can only touch when the thread is running*/
if(game.state() != STATE_PAUSE){
if(arg1.getAction() == MotionEvent.ACTION_DOWN){
coordinateX = arg1.getX();
coordinateY = arg1.getY();
differenceY = Math.abs(coordinateY - touchedY);
coordinateY = coordinateY - differenceY;
shootingIsOkay = true;
game.setDrawCircle(coordinateX,coordinateY);
}
if(arg1.getAction() == MotionEvent.ACTION_MOVE){
coordinateX = arg1.getX();
coordinateY = arg1.getY();
coordinateY = coordinateY - differenceY;
shootingIsOkay = true;
game.setDrawCircle(coordinateX,coordinateY);
}
if(arg1.getAction() == MotionEvent.ACTION_UP){
shootingIsOkay = false;
}
}
return false;
}
And the onTouch method that is called from the onTouchListener that depends on the view is just simple, here:
#Override
public boolean onTouch(View arg0, MotionEvent arg1) {
touchedY = arg1.getY();
return false;
}
If anyone knows how to fix this problem, please post your answer, i am very curious why this is happening

Consuming touch event prevents me from detecting future events

I have a problem with my app : I have a FrameLayout with a Fragment which contains a map from the Google Maps Android APi (v2), and a customized view which I use to display various buttons on top of the map.
I'd like some of these elements not to be shown while the map is being moved, for this I use the onTouchEvent() function of the View :
#Override
public boolean onTouchEvent(MotionEvent event) {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
pressed = true;
invalidate();
break;
case MotionEvent.ACTION_UP:
pressed = false;
invalidate();
break;
}
return false;
}
The onDraw() function only displays the elements drawn over the map if pressed == false;
Now, my problem is in the return : if I put false, I say the event wasn't consumed, and the Android OS no longer notifies me when touch events are recorded, thus the MotionEvent.ACTION_UP isn't detected and the buttons stay hidden. If I put true, the touch events are no longer detected this time by the GoogleMap object, and I can't move the map around. Is there a way to keep detecting all future touch events, while not consuming the first event ?
Use onInterceptTouchEvent or dispatchTouchEvent.
You may read about the differences here: Android: Difference between onInterceptTouchEvent and dispatchTouchEvent?

Android (AndEngine): How to obtain touch input events outside onSceneTouchEvent method?

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

Android multi-touch interference

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 :)

Handling drag and touch inside onTouch

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

Categories

Resources