Fling gesture detection on grid layout
Thanks to Code Shogun, whose code I adapted to my situation.
Let your activity implementOnClickListener
as usual:
public class SelectFilterActivity extends Activity implements OnClickListener {
private static final int SWIPE_MIN_DISTANCE = 120;
private static final int SWIPE_MAX_OFF_PATH = 250;
private static final int SWIPE_THRESHOLD_VELOCITY = 200;
private GestureDetector gestureDetector;
View.OnTouchListener gestureListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
/* ... */
// Gesture detection
gestureDetector = new GestureDetector(this, new MyGestureDetector());
gestureListener = new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
};
}
class MyGestureDetector extends SimpleOnGestureListener {
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
try {
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH)
return false;
// right to left swipe
if(e1.getX() - e2.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Left Swipe", Toast.LENGTH_SHORT).show();
} else if (e2.getX() - e1.getX() > SWIPE_MIN_DISTANCE && Math.abs(velocityX) > SWIPE_THRESHOLD_VELOCITY) {
Toast.makeText(SelectFilterActivity.this, "Right Swipe", Toast.LENGTH_SHORT).show();
}
} catch (Exception e) {
// nothing
}
return false;
}
@Override
public boolean onDown(MotionEvent e) {
return true;
}
}
}
Attach your gesture listener to all the views you add to the main layout;
// Do this for each view added to the grid
imageView.setOnClickListener(SelectFilterActivity.this);
imageView.setOnTouchListener(gestureListener);
Watch in awe as your overridden methods are hit, both the onClick(View v)
of the activity and the onFling
of the gesture listener.
public void onClick(View v) {
Filter f = (Filter) v.getTag();
FilterFullscreenActivity.show(this, input, f);
}
The post 'fling' dance is optional but encouraged.
Is fling gesture not supported by the Frame Layout?
Add android:clickable="true"
and android:focusable="true"
for your FrameLayout
.
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<FrameLayout
android:id="@+id/this_frameLayout"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:clickable="true"
android:focusable="true"
android:layout_marginBottom="185dp"
android:background="@color/teal_200"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent">
<Button
android:id="@+id/this_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="279dp"
android:text="Example"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
Android - swipe left|right . gesture detection
Couldn't I just say that the
LinearLayouts with the buttons are the
ones looking out for the swipe
gestures? Or because they are "hidden"
on the back of the buttons, this can't
be done?
I think that's precisely the problem you're going to face unless you detect the swipe on all visual objects.
The more buttons (or other widgets) on the screen, the more accurate a user will have to be when they start/end the swipe gesture - in other words they'd need to start/end both in gaps between your buttons.
To detect a swipe requires start and end locations - if the user starts and ends on buttons (which aren't listening for the swipe) then a swipe won't be detected. Similarly, starting on a button and ending in a 'gap' (or vice versa) won't detect a valid swipe either because only one of the start/end points is valid for 'swipe detection'.
The best approach I can think of (although I've never tried myself) is to use a GestureOverlayView. This allows you to have a transparent overlay on top of your background view(s) and can be used to detect things like 'swipe' without your underlying views needing to know about gestures.
See this in the developers resources Gestures
How to best handle fling gesture for Android ListActivity
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
}
}
Related Topics
How to Support Arabic Text in Android
How to Use Drawerlayout to Display Over the Actionbar/Toolbar and Under the Status Bar
Accepting Https Connections With Self-Signed Certificates
App Not Installed' Error on Android
Horizontal Listview in Android
"Default Activity Not Found" on Android Studio Upgrade
Can the Android Drawable Directory Contain Subdirectories
How to Send a "Multipart/Form-Data" Post in Android With Volley
This App Won't Run Unless You Update Google Play Services (Via Bazaar)
Basic Communication Between Two Fragments
What's the Difference Between the Various Methods to Get an Android Context
How to Scale an Image in Imageview to Keep the Aspect Ratio
Filter Logcat to Get Only the Messages from My Application in Android
Android Fragment Handle Back Button Press
Different Resolution Support Android
How to Use Inputfilter to Limit Characters in an Edittext in Android