带有ListView的界面无法通过手势左右滑动切换界面问题解决办法
问题描述:
在做OnGestureListener滑动切换窗口的时候,会遇到这样的问题。就是当界面中含有ListView的时候,OnGestureListener的左右触屏滑动就被ListView自己吃掉了。
问题分析:
在Android系统中,事件的分发和响应都按照一定的优先级仅仅有条的进行着。如果Activity中包含ListView那么系统的onTouchEvent事件会优先分发给ListView去处理,这时ListView的OnItemClickListener监听器会优先响应onTouchEvent事件。从而导致GestureDetector无法接收到系统的onTouchEvent事件。
解决方法:
解决方法主要有两种:
第一种:改变系统分发的onTouchEvent事件的顺序。这种方式比较简单。
第二种:自定义ListView使其支持GestureDetector的OnGestureListener。这种方式相对于第一种方式比较复杂。
下面就具体介绍两种方式的在具体做法。
第一种:改变系统分发的onTouchEvent事件的顺序:
/**
* 重写此方法将触控事件优先分发给GestureDetector,以解决滑动ListView无法切换屏幕的问题、
* */
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
// TODO Auto-generated method stub
this.gestureDetector.onTouchEvent(ev);
return super.dispatchTouchEvent(ev);
}
第二种:自定义ListView使其支持GestureDetector的OnGestureListener:
第一步:自定义ListView:
/**
*自定义带有手势的listview,
*/
class GestureList extends ListView {
int flag=BaseActivity.flag;
Context context;
GestureDetector gestureDetector;
/**
* 在xml布局里面使用GestureList,默认的会调用这个构造方法
* @param context
* @param attrs
*/
public GestureList(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
this.context=context;
gestureDetector=new GestureDetector(context,new Gesture(context));
}
public GestureList(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
this.context=context;
gestureDetector=new GestureDetector(context,new Gesture(context));
}
public GestureList(Context context) {
super(context);
// TODO Auto-generated constructor stub
this.context=context;
gestureDetector=new GestureDetector(context,new Gesture(context));
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if(gestureDetector.onTouchEvent(ev)) return true;
return super.onTouchEvent(ev);
}
}
第二步:为自定义的ListView创建手势监听器:
public class Gesture implements OnGestureListener{
/**得到全局的标志位**/
int flag=BaseActivity.flag;
/**要切换有切换的activity的个数**/
int length=BaseActivity.myClass.length;
@SuppressWarnings("rawtypes")
/**得到activity数组 **/
Class[] myClass=BaseActivity.myClass;
Context context;
public Gesture(Context context) {
// TODO Auto-generated constructor stub
this.context=context;
}
@Override
public boolean onDown(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
}
@Override
/**
* 滑动事件的处理
*/
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
//左滑动
if (e1.getX() - e2.getX() > 50) {
Log.i("Fling", "Gesture:左滑动 ");
if (++flag>=length) {
flag=length-1;
//改变BaseActivity,让其知道标志位改变了
BaseActivity.flag=flag;
return true;
}
BaseActivity.flag=flag;
Intent intent=new Intent(context, myClass[flag]);
//用这个FLAG启动的Activity,一旦退出,就不会存在于栈中
intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY|Intent. FLAG_ACTIVITY_REORDER_TO_FRONT);
//需要context才能启动activity
context.startActivity(intent);
return true;
}
//右滑动
else if (e2.getX() - e1.getX()>50) {
Log.i("Fling", "Gesture:右滑动 ");
if (--flag<0) {
flag=0;
//改变BaseActivity,让其知道标志位改变了
BaseActivity.flag=flag;
return true;
}
BaseActivity.flag=flag;
Intent intent=new Intent(context,myClass[flag]);
//用这个FLAG启动的Activity,一旦退出,就不会存在于栈中
intent.setFlags(Intent. FLAG_ACTIVITY_NO_HISTORY|Intent. FLAG_ACTIVITY_REORDER_TO_FRONT);
//需要context才能启动activity
context.startActivity(intent);
// System.exit(0);//退出当前Activity
return true;
}
return true;
}
}
第三步:在布局界面引用自定义的ListView:
<com.jph.custom.GestureList android:id="@+id/list"
android:layout_height="match_parent"
android:layout_width="wrap_content"
android:focusable="false"
/>