I'm trying to create gesture recognition in my Android app that will respond to the fling gesture and change the view accordingly. A little background info: my activity consists of two side by side views in a Linear layout.
The problem i'm having is that the onFling() method is never triggered despite the fling gesture being performed on the device's screen.
Here is my gesture recognition handler class, GestureListener.java:
package com.example.guitarsim;
//this class is designed to listen for touch events corresponding to the fling gesture
import android.content.Context;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;
class GestureListener extends SimpleOnGestureListener implements OnTouchListener {
Context mContext;
GestureDetector gDetector;
static final double SWIPE_MIN_DISTANCE = PlayFrets.getActualHeight()*(0.05); //must swipe across at least 5% of screen height to register a gesture
static final int SWIPE_MAX_OFF_PATH = 150;
static final int SWIPE_THRESHOLD_VELOCITY = 100;
public GestureListener(Context context) {
this.mContext = context;
}
public GestureListener(Context context, GestureDetector gDetector) {
if (gDetector == null){
gDetector = new GestureDetector(context, this);
}
this.mContext = context;
this.gDetector = gDetector;
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gDetector.onTouchEvent(event);
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,float velocityY) {
Log.e("gesture", String.valueOf(SWIPE_MIN_DISTANCE));
if (Math.abs(e1.getY() - e2.getY()) > SWIPE_MAX_OFF_PATH) {
if (Math.abs(e1.getX() - e2.getX()) > SWIPE_MAX_OFF_PATH || Math.abs(velocityY) < SWIPE_THRESHOLD_VELOCITY) {
return false;
}
else if (e1.getY() - e2.getY() > SWIPE_MIN_DISTANCE) {
//float traveled = e1.getY() - e2.getY();
//Toast.makeText(context, Float.toString(traveled) + ">" +String.valueOf(SWIPE_MIN_DISTANCE),Toast.LENGTH_SHORT).show();
Toast.makeText(mContext, "Swiped Up",Toast.LENGTH_SHORT).show();
}
else if (e2.getY() - e1.getY() > SWIPE_MIN_DISTANCE) {
//float traveled = e2.getY() - e1.getY();
//Toast.makeText(context, Float.toString(traveled) + ">" +String.valueOf(SWIPE_MIN_DISTANCE),Toast.LENGTH_SHORT).show();
Toast.makeText(mContext, "Swiped Down",Toast.LENGTH_SHORT).show();
}
}
return super.onFling(e1, e2, velocityX, velocityY);
}
public GestureDetector getDetector() {
return gDetector;
}
}
EDIT Here is my main activity class where i instantiate my GestureListener object, PlayFrets.java
public class PlayFrets extends Activity {
LinearLayout gestureOverlay;
GestureListener gestureListener;
public void configGestureRecognition(){ //Toolbar gesture recognition
gestureOverlay = (LinearLayout) findViewById(R.id.toolbarGestureOverlay);
gestureListener = new GestureListener(PlayFrets.this);
if (gestureOverlay == null){
Toast.makeText(PlayFrets.this, "gestureOverlay object is null bro" ,Toast.LENGTH_SHORT).show();
}
gestureOverlay.setOnTouchListener(gestureListener);
}
}
EDIT I have also included my class running an Asynctask when the app starts up that calls the method in my main activity that runs my GestureListener instantiation code and sets the view, LoadNoteFiles.java:
public class LoadNoteFiles extends AsyncTask<Void, Void, Void>{
private Context mContext;
Activity instance;
public LoadNoteFiles(Context context){ //constructor
mContext = context;
}
@Override
protected void onPreExecute(){
PlayFrets.viewSwitch = new ViewSwitcher(mContext);
PlayFrets.viewSwitch.addView(ViewSwitcher.inflate(mContext, R.layout.splash_screen, null));
instance = (Activity)mContext; //cast context from main activity into an activity to access setContentView method
instance.setContentView(PlayFrets.viewSwitch);
}
...//do in background code omitted
@Override
protected void onPostExecute(Void v){
PlayFrets.viewSwitch.addView(ViewSwitcher.inflate(mContext, R.layout.activity_play_frets, null));
PlayFrets.viewSwitch.showNext();
((PlayFrets)mContext).configFretboard();
((PlayFrets)mContext).configGestureRecognition(); //test gesture recognition
}
And here is my xml file. *Note that the view i'm trying to detect gestures on is the linear layout with id toolbarGestureOverlay.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:baselineAligned="false"
android:keepScreenOn="true">
<LinearLayout
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_weight="1"
android:background="@drawable/gold_guitarsim_text"
android:orientation="vertical"
android:id="@+id/toolbarGestureOverlay" >
</LinearLayout>
<LinearLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:orientation="vertical"
android:layout_weight="4">
<com.example.guitarsim.Multitouch
android:id="@+id/fretBoard"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:background="@drawable/fret_board1" />
</LinearLayout>
</LinearLayout>
So here are my questions; Whats preventing GestureListener's onFling() method from being reached? Also, is my xml file correctly set up? Specifically; do I need to label the linear layout i'm trying to detect gestures on, like i did with myother linear layout (com.example.guitarsim.Multitouch) to effectively control it within my program?