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;
}
}
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;
}
}