GridView 滑动 事件

场景:Gridview的手势滑动与onItemClick事件有冲突?解决思路

Gridview的手势滑动与onItemClick事件有冲突?
我用ViewFlipper实现了多页Gridview的滑屏效果。问题是,当OnFling事件发生时,往往也会伴随着发生Gridview的onItemClick事件。(我既希望处理OnFling实现多页滑屏,也希望能够处理每页中Gridview的元素单击事件,但是不希望两者同时发生,否则就有冲突了。)具体代码如下:
public class MainActivity_TabContentActivity extends Activity
{
public class MYGestureListener extends SimpleOnGestureListener implements OnTouchListener {  
private GestureDetector m_gestureDetector;
  
public MYGestureListener(){  
super();  
}

public MYGestureListener(Context con){ 
this.m_gestureDetector = new GestureDetector(con, this);
}

public GestureDetector getGestureDector(){  
return this.m_gestureDetector;  
}

public boolean onTouch(View v, MotionEvent event) {  
return m_gestureDetector.onTouchEvent(event);  
}
  
@Override  
public boolean onSingleTapConfirmed(MotionEvent e) {  
return super.onSingleTapConfirmed(e);  
}  
  
@Override  
public boolean onFling(MotionEvent event1, MotionEvent event2, float velocityX, float velocityY) { 

  if (event1.getX() - event2.getX() > 50)
  {
m_vfDishList.showNext();
  return true;
  }
  else if (event2.getX() - event1.getX() > 50)
  {
  m_vfDishList.showPrevious();
  return true;
  }
   
return true;  
}  
}

public class MySimpleAdapter extends SimpleAdapter {  
public MySimpleAdapter(Context context,  
List<? extends Map<String, ?>> data, int resource,  
String[] from, int[] to) {  
super(context, data, resource, from, to);  
}  
 
@Override  
public View getView(int position, View convertView, ViewGroup parent) {  
View v = super.getView(position, convertView, parent);  
 
// 构造并返回Gridview所需的View
  // ......  
 
return v;  
}  
}

ArrayList<String> m_arDishes = new ArrayList<String>();
MyViewFlipper m_vfDishList;
MYGestureListener m_gestureListener;

  /** Called when the activity is first created. */
  @Override
  public void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);  
  setContentView(R.layout.main_dishlist_tabcontent);  

// 获得数据,存入m_arDishes中
  ......
   
  // 分页创建GridView, 并将每页GridView加入ViewFlipper中
  m_gestureListener = new MYGestureListener(this);  
  for (int i = 1; i <= m_iTotalPage; i++)
  {
GridView gvDishList = new GridView(this);
  FrameLayout.LayoutParams lp = new FrameLayout.LayoutParams(FrameLayout.LayoutParams.MATCH_PARENT,
  FrameLayout.LayoutParams.WRAP_CONTENT);
  gvDishList.setLayoutParams(lp);
  gvDishList.setGravity(0);
  gvDishList.setNumColumns(3);
  gvDishList.setHorizontalSpacing(10);
  gvDishList.setVerticalSpacing(10);
  gvDishList.setColumnWidth(90);
  gvDishList.setStretchMode(GridView.STRETCH_COLUMN_WIDTH);
  gvDishList.setOnTouchListener(m_gestureListener);  
  gvDishList.setOnItemClickListener(m_gvClickListener);
  gvDishList.setOnItemLongClickListener(new OnItemLongClickListener(){
public boolean onItemLongClick(AdapterView<?> arg0, View arg1,
int arg2, long arg3) {
// ....
return true;
}
  });  
   
  ArrayList<HashMap<String,Object>> sourceList = new ArrayList<HashMap<String,Object>>();
  // 构造SourceList
  // ......
 
  gvDishList.setAdapter(new MySimpleAdapter(this, sourceList, R.layout.gridviewitem_dishlist,  
new String[]{"tvDish"}, 
new int[]{R.id.tvDish}));
   
  m_vfDishList.addView(gvDishList);
  }  
  }
   
  private OnItemClickListener m_gvClickListener = new OnItemClickListener() {  
  public void onItemClick(AdapterView<?> parent, View view, int position,  
  long id) {
  // 处理Gridview的Item单击事件
// ....
  }  
  };
}

------解决方案--------------------
你需要重写一下GridView,代码如下,最后还要调用gridView.setGestureDetector(m_gestureListener )
package com.puyo.trip.tripbook.view;

import android.content.Context;
import android.util.AttributeSet;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.GridView;

public class MyGridView extends GridView {

GestureDetector gestureDetector;
public MyGridView(Context context) {
super(context);
}

public MyGridView(Context context,AttributeSet attrs) {
super(context,attrs);
}

public void setGestureDetector(GestureDetector gestureDetector){
this.gestureDetector=gestureDetector;
}

@Override
public boolean onTouchEvent(MotionEvent ev) {
super.onTouchEvent(ev);
return gestureDetector.onTouchEvent(ev);
}

@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
gestureDetector.onTouchEvent(ev);
super.dispatchTouchEvent(ev);
return true;
}
}

------解决方案--------------------
我也遇到了这个问题,不过已经解决了,二楼说得对,你需要重写GridView.onTouch,自己来识别手势,不要用GridView缺省的手势处理(即不要调用super.onTouch),而自己来控制什么情况产生onItemClick事件,帖上我的部分代码给楼主参考一下:

private class OnGestureListener extends GestureDetector.SimpleOnGestureListener
{
@Override
public boolean onDown(MotionEvent e) {
return true;
}


@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//如果按下,并且移动,就标志取消onItemClick事件
if (e2.getAction() == MotionEvent.ACTION_MOVE) {

if (Math.abs(distanceX) >5 || Math.abs(distanceY) >5)
{
mHandlerClick = false;
if (mHitView != null)
{
mHitView.setPressed(false);
mHitView.setSelected(false);
}
}
}
return true;
}

@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
return false;
}
@Override
public void onLongPress(MotionEvent e) {
// Finalise scrolling
}

@Override
public void onShowPress(MotionEvent e) {
//按下时,取得当前点击的item view
mHandlerClick = true;
int x = (int) e.getX();
int y = (int) e.getY();
int pos = GalleryViewItem2.this.pointToPosition(x, y);
mHitView = GalleryViewItem2.this.getChildAt(pos); 
if (mHitView != null)
{
mHitView.setPressed(true);
mHitView.setSelected(true);
}
}

@Override
public boolean onSingleTapUp(MotionEvent e) {
// Reset fling state
if (mHitView != null)
{
mHitView.setPressed(false);
mHitView.setSelected(false);
}
return true;
}

@Override
public
boolean onSingleTapConfirmed(MotionEvent e)
{
//按下后,如果事件没有被取消,调用onItemClick的处理过程
if (mHitView != null)
{
mHitView.setPressed(false);
mHitView.setSelected(false);
}

if (mHandlerClick && mHitView != null)
{
if (GalleryViewItem2.this.getOnItemClickListener() != null)
GalleryViewItem2.this.getOnItemClickListener().onItemClick(null, mHitView, 0, 0);
}
return true;
}
}