我用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单击事件
// ....
        }  
    };
}

解决方案 »

  1.   

    你需要重写一下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;
    }
    }
      

  2.   

    非常感谢kechanghe0705的帮助,我会按照你的方法尝试一下。另外,能否解释一下为什么要这样做呢,特别是重载onTouchEvent和dispatchTouchEvent的原因和目的。还有,如果按照你的方法,那我自定义的MYGestureListener是否只需要继承SimpleOnGestureListener,不再需要实现OnTouchListener接口,MYGestureListener::OnFling返回true是否正确呢,如果返回false,下次好像就收不到onFling事件了?
      

  3.   

    kechanghe0705:按照您的建议,我修改了我的代码,如下:
    public class GridViewEx extends GridView {
    GestureDetector m_gestureDetector;

    public GridViewEx(Context context) {
    super(context);
    } public GridViewEx(Context context,AttributeSet attrs) {
    super(context,attrs);
    } public void setGestureDetector(GestureDetector gestureDetector){
    this.m_gestureDetector = gestureDetector;
    } @Override
    public boolean onTouchEvent(MotionEvent ev) {
    super.onTouchEvent(ev);
    return m_gestureDetector.onTouchEvent(ev);
    } @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    m_gestureDetector.onTouchEvent(ev);
    super.dispatchTouchEvent(ev);
    return true;
    }
    }public class MainActivity_TabContentActivity extends Activity
    {
    public class MyGestureListener extends SimpleOnGestureListener {
    public MyGestureListener(){  
        super();  
    }
      
    @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;
    GestureDetector m_gestureDetector;        @Override
            public void onCreate(Bundle savedInstanceState) {
                super.onCreate(savedInstanceState);        
                setContentView(R.layout.main_dishlist_tabcontent);      // 获得数据,存入m_arDishes中
            
                // 分页创建GridView, 并将每页GridView加入ViewFlipper中
                m_gestureListener = new MyGestureListener();    
                m_gestureDetector = new GestureDetector(m_gestureListener);
                for (int i = 1; i <= m_iTotalPage; i++)
                { 
             GridViewEx gvDishList = new GridViewEx(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.setGestureDetector(m_gestureDetector);
                    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上,当按下手指,做手势滑动操作时,onFling事件和onItemClick事件先后被同时触发了。我期望的效果是,当在Gridview上当进行左右滑动时,仅执行onFling事件处理;当点击Gridview上某项时,仅执行onItemClick事件处理。
    谢谢。
      

  4.   

    我以前遇见过ViewFlipper和listview冲突的时候,这个没有遇见过。
      

  5.   

    感谢summersrest的帮助,那您是如何解决的呢?谢谢。
      

  6.   

    重写 Activity的dispatchTouchEvent()可以解决这个问题 @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    Activity.this.detector.onTouchEvent(ev);
    return super.dispatchTouchEvent(ev);
    }
      

  7.   

    我也遇到了这个问题,不过已经解决了,二楼说得对,你需要重写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;
                }
            }
      

  8.   

    重写 Activity的dispatchTouchEvent()可以解决这个问题@Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
    Activity.this.detector.onTouchEvent(ev);
    return super.dispatchTouchEvent(ev);
    }   可以搞定!