I have a listview that displays entries for a given date. There are buttons above the listview that allow you to increase/decrease the date. Everything works. What I'm looking to do is replace those buttons and have the user swipe right/left to increase/decrease the date.
What's the best way to go about this? I don't care what item is swiped, often there will be no items in the listview for a given date, just as long as it happens on the listview area. I do have click and longclick listeners on the items already.
Just implement the OnGestureListener.
public class MyListActivity extends ListActivity implements OnGestureListener
Use a GestureDetector
GestureDetector detector = new GestureDetector(this, this);
Pass the touch event of the list to the GestureDetector
listView.setOnTouchListener(new OnTouchListener() {
public boolean onTouch(View view, MotionEvent e) {
detector.onTouchEvent(e);
return false;
}
});
And finally use the fling method to detect a gesture. You can use the velocity values to detect the direction of the movement.
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {}
Related
I have a horizontal RecyclerView. I need to scroll it but to disable fling by swipe gesture.
Originally all work is done at onTouchEvent method and I dont know how to disable it without rewriting all touch handling
You can use a GestureDetector with a SimpleOnGestureListener to capture fling events and decide whether or not to allow them.
RecyclerView recycler = findViewById(R.id.recycler);
GestureDetector detector = new GestureDetector(this, new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
// return true if you want to stop the fling
// return false if you want to allow the fling
return true;
}
});
recycler.setOnTouchListener((v, event) -> detector.onTouchEvent(event));
GestureDetector.OnGestureListener#onFling()
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'm implementing a swipe gesture similar to the one in Android Gmail app where you drag across an item to archive it.
I attach a touch listener to the item view and a gesture detector and listener to listen to touch events like this:
GestureDetector.OnGestureListener gl;
gl = new GestureDetector.SimpleOnGestureListener() {
#Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float dx, float dy) {
// ... handle horizontal scrolling
return true;
}
};
final GestureDetector gd = new GestureDetector(getContext(), gl);
itemView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent e) {
gd.onTouchEvent(e);
// ... handle TOUCH_UP and TOUCH_CANCEL
return true;
}
});
The problem is that as soon as I start dragging vertically, or go outside the bounds of the item view, the gesture is cancelled and list view starts handling it for normal vertical list scrolling. I need the gesture to not cancel until the user releases the finger, even if it moves outside the table cell, like it's done in Gmail app.
How do I have it not cancelled?
I have an Android app with a ListActivity in the main view. The list contains a LinearLayout with a TextView and a hidden delete Button. The delete Button will be hidden by default. I want to use a fling gesture to show the button. I am able to detect the fling gesture thanks to question #937313 on stackoverflow. It's not clear to me how to determine which item in the list was flung, since the onTouch listener listens to the ListView. The item is not necessarily selected so getSelected* methods can't be used reliably. I am using the SimpleListAdaptor so I don't have direct access to the View Objects in the ListView.
Any ideas?
Try using AbsListView.pointToPosition() to determine the list item for the X,Y coordinate in your list view.
If you're using the recipe from #937313, you should be able to override onFling() more or less as follows:
#Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
Toast.makeText(listAdapter.getItem( listView.pointToPosition( (int) e1.getX(), (int) e1.getY() ).toString() );
return super.onFling();
} catch( Exception e ) {
// do nothing
}
}