I'm replicating my IOS App that heavily uses Pan Gesture Recognizer to Android and I couldn't find similar
Gesture recognizer. Is there such thing?
any direction is appreciated thanks
Android comes out of the box with two classes that recognize gesture. One is GestureDetector and the other is ScaleGestureDetector.
Unlike, ios, the basic gesture detector framework is limited - you can't specify dependencies, do conflict resolution or configure them by specifying touch points etc like you can in ios's UiGestureRecognizer class.
To answer your question, pan can be detected using the GestureDetector. Here is a snippet:
PanGestureListener listener = new PanGestureListener();
GestureDetector detector = new GestureDetector(context, listener);
class PanGestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onScroll(MotionEvent e1,
MotionEvent e2,
float distanceX,
float distanceY) {
//YOUR "pan handler"
return true;
}
}
Now in your onTouch method just forward all the calls to detector.onTouch like this:
#Override
public boolean onTouchEvent(MotionEvent event) {
detector.onTouchEvent(event);
return true;
}
I think what you're looking for is GestureDetector. I'm not very familiar with iOS's Pan Gesture Recognizer, but I think it does't work exactly the same way in Android. See the developer guide topic Using Touch Gestures for info on how to use the class.
Related
I'm trying to detect a onFling event on the entire area of my activity. To do this I:
1) set the GestureDetectorCompat:
private GestureDetectorCompat gDetect;
2) in OnCreate initialize the detector:
gDetect = new GestureDetectorCompat(this, new GestureListener());
3) override the onTouchEvent:
#Override
public boolean onTouchEvent(MotionEvent event) {
gDetect.onTouchEvent(event);
return super.onTouchEvent(event);
}
4) create the GestureListener class:
class GestureListener extends GestureDetector.SimpleOnGestureListener {
#Override
public boolean onDown(MotionEvent event) {
return true;
}
#Override
public boolean onFling(MotionEvent event1, MotionEvent event2,
float velocityX, float velocityY) {
Log.e(null, "onFling: " + event1.toString() + event2.toString());
return super.onFling(event1, event2, velocityX, velocityY);
}
}
It works, but it detects onFling gesture ONLY in the part of my UI where there is not any other view. So, if I swipe in a blank area it works, if I swipe in a part of the activity where is another view (for example a ScrollView or a LinearLayout) the detection isn't triggered.
I hope I've explained my problem: how I can detect gesture on the entire surface of the Activity, to accomplish a simple swipe gesture?
Many tanks.
You can use GestureOverlayView. Here is a great starter resource for GestureOverlayView . Also you can have a look at this SO question.
Basically to use this your application must use the view "GestureOverlayView" and you place your other views in this view. Your activity must implement the interface "OnGesturePerformedListener" and if a gesture is detected then "onGesturePerformedListener" method is called.
Hope this helps. Goodluck!
I am facing a situation.
I have written a class implementing onTouchListener which I have registered with view(GLSurfaceView, to be precise) and I used it to extract all
information about touch events. And it serves me very well. And implementing onTouch
method means that event is handled then and there and its not propagated down.
But of late I need to implement swipe functionality for my game. And it needs that I implement
onTouchEvent for my view. But as my onTouchListener implementation class is already implementing onTouch method, so onTouchEvent won't be called. And I want to keep my onTouchListener implementation.
Please tell me how to solve this issue.
Manish
In your class put the following:
//not necessarily OnCreate but put it in whatever constructor your class uses
OnCreate(Context context){
mGestureDetector = new GestureDetector(context, new CustomGestureListener());
}
#Override
public boolean onTouchEvent(MotionEvent event) {
mGestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
private final GestureDetector mGestureDetector;
private class CustomGestureListener extends SimpleOnGestureListener {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//get the fling
}
}
This allows the onTouchEvent to execute, but it also checks for a gesture event as well by calling the gesture detector within the onTouchEvent.
See also this answer: How to set OnTouchListener for the entire screen?
I am working in android. I have some functionality which is to be done on these following methods:-
1. MotionEvent.ACTION_DOWN
2. MotionEvent.ACTION_UP
3. MotionEvent.ACTION_MOVE
and i also want to do fling() on that image.
For above requirement i implemented onGestureListener and onTouchListener in my application, but these are not working properly. onTouchListener is working but onGestureListener is not working. When i remove onTouchListner code then onGestureListener is working correctly.
So please suggest me what should i do for this. I want to implement these four methods in my application.
1. MotionEvent.ACTION_DOWN
2. MotionEvent.ACTION_UP
3. MotionEvent.ACTION_MOVE
4. onFling
You can acheive this by implementing the OnGestureListener from your activity overriding the below methods
// For touch
public boolean onSingleTapUp(MotionEvent event) { return false; }
// For Fling
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
return false;
}
Hope this helps.
EDIT 1: Detailed explanation:
1> implement the OnGestureListener from your activity
public class MyActivity implements OnGestureListener
2> create an instance of GestureDetector:
private GestureDetector gestureScanner;
And at onCreate:
// Avoid a deprecated constructor
// (http://developer.android.com/reference/android/view/GestureDetector.html)
gestureScanner = new GestureDetector(this, this);
3> Override the below methods:
#Override
public boolean onTouchEvent(MotionEvent event) {
return gestureScanner.onTouchEvent(event);
}
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
/* on scroll to the next page in story */
if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
// ...
}
/* on scroll to the previous page in story */
else if (e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE
&& Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
// ...
}
return false;
}
#Override
public boolean onSingleTapUp(MotionEvent event) {
return false;
}
EDIT 2: For handling Move
Override the onScroll method have a look at the details here
Just as a word of advice coming from a fellow Android developer who has chased down the primrose path of the swipe or fling event... When writing a listener or trying to implement the OnGestureListener class be sure to have import android.view.GestureDetector.OnGestureListener in your imports.
Otherwise the OnGesturListener will be using a GestureOverlayView's imports and that's not what it seems you are looking for. Those are helpful especially when trying to implement gesture captures using the Gestures application and importing the saved gestures and creating a Gestures Library for your application during run time to then "predict" what the user is doing by running some fancy algorithm in the background and seeing who deviates the least from the user's input. Which turns out to be an array of locations that came in from the OS as the dragged their little stubby fingers across the flat screen... It's a different approach than just trying to capture a fling, or long press. Which seems as what the users are looking for above and not some fancy multi-press gesture capture, which this approach makes very simple. This technique is also very helpful in video games and giving possibly a "backdoor" to any people out there who like to develop games. Or in the 9-5 world, to put a Support or Admin backdoor into your mobile application to hide some settings or logs from everyday users. In which one can also use the above intended techniques but then you have to get an array of points, or locations across the screen and it gets tedious for any non-math people or self taught developers. Hope I contributed or helped anyone. No one mentioned this to me when I was learning this and I never found it in any of the several books I have read about Android also.
I'm playing around with an app I have written whose main activity is a TabActivity. I was considering allowing the user to navigate between tabs with a fling gesture, but I find that I can only detect flings on one of my four tabs.
public class WSGesture extends TabActivity implements OnGestureListener {
private GestureDetector gestureScanner;
#Override onCreate(Bundle savedInstanceState)
{
gestureScanner = new GestureDetector(this);
...
}
.
.
.
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
Log.v(TAG, "onFling called, velX: " + velocityX + ", velY: " + velocityY);
return true;
}
public boolean onTouchEvent(MotionEvent me)
{
return gestureScanner.onTouchEvent(me);
}
}
When I execute this code, I only see onFling being called when one particular tab is set as the current tab. For the other three, I get nothing. It's always the third out of four, if that matters.
One thing that has worked for me in the past is implementing onDown() and returning true...
When doing this though, be careful... I have found that the behavior when doing this is different between the 1.x and 2.x versions of Android when using your onGestureListener to handle other things like single clicks... so be sure to thoroughly test your app when making changes like this.
If you are only using onFling then you "should" be ok... but test it just to be safe.
I am a new user of google maps API in android OS. I have made a small application in which i am using google maps. I want to add a functionality that when i double click (multi touch) on a map the map should zoom in. IS there anybody who has an idea how to do this or if it is possible please provid a code example.
Thanks in advance.
BR,
SilentCoders
I've done something like this in an app using maps api. Although I did this in an overlay item, the principle should be the same.
You could try using TouchListener and GestureDetector to detect the touch events and such.
Note that this is not all actual working code, you need to adopt it so it fits into your implementation.
...
class MyDetector extends SimpleOnGestureListener {
#Override
public boolean onDoubleTap(MotionEvent event) {
mapView.getController().zoomInFixing((int) event.getX(), (int) event.getY());
return super.onDoubleTap(
}
}
// maybe do this in your init or something
GestureDetector gDetector = new GestureDetector(new MyDetector());
mapView.setOnTouchListener(new OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
return gDetector.onTouchEvent(event);
}
});
Something like that "should" work :)