I'm practicing with SimpleGestureListener and I can catch the fling events just fine, but even when my onFling() returns true, the fragments in the layout catch the fling and react to it. I don't want this to happen.
The activity has a ViewPager that loads fragments (these fragments load images from a folder in the SD card, and there're as many framments added to the ViewPager as images are in the folder). I've attached my custom GestureListener to the RelativeLayout that serves as main container of the activity's layout. I've only overridden the onFling() event.
Code as follows:
Activity:
public class MainActivity extends FragmentActivity {
private GestureDetector gestureDetector;
private ViewPager vwpMain;
private PagerAdapter pgaMain;
private RelativeLayout layout;
private LinearLayout topLayout, bottomLayout;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.activity_main);
layout = (RelativeLayout) findViewById(R.id.container);
topLayout = (LinearLayout) findViewById(R.id.topPanel);
bottomLayout = (LinearLayout) findViewById(R.id.bottomPanel);
vwpMain = (ViewPager) findViewById(R.id.vwpMain);
pgaMain = new MyPagerAdapter(getSupportFragmentManager());
vwpMain.setAdapter(pgaMain);
gestureDetector = new GestureDetector(this, new MyGestureListener(
getApplicationContext(), topLayout, bottomLayout));
layout.setOnTouchListener(new OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
gestureDetector.onTouchEvent(event);
return true;
}
});
}
public boolean dispatchTouchEvent(MotionEvent ev) {
super.dispatchTouchEvent(ev);
return gestureDetector.onTouchEvent(ev);
}
private class MyPagerAdapter extends FragmentPagerAdapter {
public MyPagerAdapter(FragmentManager fragmentManager) {
super(fragmentManager);
}
@Override
public Fragment getItem(int pos) {
return ImageFragment.create(pos);
}
@SuppressLint("SdCardPath")
@Override
public int getCount() {
File f = new File("/mnt/sdcard/FragmentImages/");
return f.listFiles().length;
}
}
}
GestureListener:
public class MyGestureListener extends SimpleOnGestureListener {
private static final int SWIPE_MIN_DISTANCE = 75;
private static final int SWIPE_MAX_OFF_PATH = 100;
private static final int SWIPE_THRESHOLD_VELOCITY = 50;
public Context context;
public View topView, bottomView;
private enum ActivePanel {
Top, Bottom, None
}
private ActivePanel currentPanel;
public MyGestureListener(Context _context, View top, View bottom) {
super();
context = _context;
topView = top;
bottomView = bottom;
currentPanel = ActivePanel.None;
}
// @Override
// public boolean onDown(MotionEvent event) {
// return true;
// }
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
boolean result = false;
float dX = e2.getX() - e1.getX();
float dY = e1.getY() - e2.getY();
if (Math.abs(dY) < SWIPE_MAX_OFF_PATH
&& Math.abs(velocityX) >= SWIPE_THRESHOLD_VELOCITY
&& Math.abs(dX) >= SWIPE_MIN_DISTANCE) {
if (dX > 0) {
Log.d("Fragment", "Swiping right");
} else {
Log.d("Fragment", "Swiping left");
}
if (currentPanel != ActivePanel.None) {
result = true;
}
} else if (Math.abs(dX) < SWIPE_MAX_OFF_PATH
&& Math.abs(velocityY) >= SWIPE_THRESHOLD_VELOCITY
&& Math.abs(dY) >= SWIPE_MIN_DISTANCE) {
if (dY > 0) {
Log.d("Fragment", "Swiping up");
switch (currentPanel) {
case None:
// Show bottom panel
Animation showBottomPanel = AnimationUtils.loadAnimation(
context, R.anim.show_bottom);
bottomView.bringToFront();
bottomView.startAnimation(showBottomPanel);
bottomView.setVisibility(View.VISIBLE);
currentPanel = ActivePanel.Bottom;
break;
case Top:
// Hide top panel
Animation hideTopPanel = AnimationUtils.loadAnimation(
context, R.anim.hide_top);
topView.bringToFront();
topView.startAnimation(hideTopPanel);
topView.setVisibility(View.GONE);
currentPanel = ActivePanel.None;
break;
case Bottom:
// Do nothing
break;
}
} else {
Log.d("Fragment", "Swiping down");
switch (currentPanel) {
case None:
// Show top panel
Animation showTopPanel = AnimationUtils.loadAnimation(
context, R.anim.show_top);
topView.bringToFront();
topView.setVisibility(View.VISIBLE);
topView.startAnimation(showTopPanel);
currentPanel = ActivePanel.Top;
break;
case Top:
// Do nothing
break;
case Bottom:
// Hide bottom panel
Animation hideBottomPanel = AnimationUtils.loadAnimation(
context, R.anim.hide_bottom);
bottomView.bringToFront();
bottomView.startAnimation(hideBottomPanel);
bottomView.setVisibility(View.GONE);
currentPanel = ActivePanel.None;
break;
}
}
result = false;
} else {
result = false;
}
return result;
}
}
Layout:
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin_noborder"
android:paddingLeft="@dimen/activity_horizontal_margin_noborder"
android:paddingRight="@dimen/activity_horizontal_margin_noborder"
android:paddingTop="@dimen/activity_vertical_margin_noborder"
tools:context=".MainActivity" >
<LinearLayout
android:id="@+id/topPanel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#88000000"
android:gravity="center"
android:orientation="horizontal"
android:visibility="gone" >
<TextView
android:id="@+id/topPanelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/topPanelText"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/white" />
</LinearLayout>
<LinearLayout
android:id="@+id/bottomPanel"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="#88000000"
android:gravity="center"
android:orientation="horizontal"
android:visibility="gone" >
<TextView
android:id="@+id/bottomPanelTextView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/bottomPanelText"
android:textAppearance="?android:attr/textAppearanceLarge"
android:textColor="@android:color/white" />
</LinearLayout>
<android.support.v4.view.ViewPager
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/vwpMain"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</RelativeLayout>
In case someone is struggling with this, I found a great answer here: http://blog.svpino.com/2011/08/disabling-pagingswiping-on-android.html
Basically, create a new class that inherits from ViewPager as follows:
and then change your ViewPager in your layout to the new class instead:
Each time you want to disable viewpager interaction, call setPagingEnabled with false and with true to reeenable.