无法同时处理点击和触摸事件

我正在尝试处理触摸事件并单击button上的事件。 我做了以下几点:

button.setOnClickListener(clickListener); button.setOnTouchListener(touchListener); 

当任何一个监听器注册的东西工作正常,但是当我尝试使用它们时,只有触摸事件被触发。 任何解决方法? 我究竟做错了什么?

ClickListenerTouchListener之间有一个细微的但非常重要的区别。 TouchListener在视图可以响应事件之前执行。 ClickListener只有在视图处理后才会收到它的事件。

所以当你触摸你的屏幕时, TouchListener被执行,当你的事件返回true时, ClickListener将永远不会得到它。 但是,如果按下设备的轨迹球,则应触发TouchListener因为TouchListener不会对其作出响应。

它有点棘手。

如果你设置了onTouchListener你需要在ACTION_DOWN返回true ,告诉系统我已经消费了这个事件,并且不会滴onTouchListener其他的监听器。

但是,那么OnClickListener将不会被解雇。

所以你可能会想,我会在那里做我的事情,并返回false所以我也可以收到点击。 如果你这样做,它会工作,但你不会订阅其他即将到来的触摸事件( ACTION_MOVEACTION_UP )因此,唯一的select是在那里返回true ,但是那么你将不会收到任何点击事件,如我们所说先前。

所以你需要在ACTION_UP手动执行view.performClick()

这将工作。

感谢@urSus的伟大答案
但在这种情况下,每个触摸将执行点击,即使ACTION_MOVE
假设你想分开move事件和click事件,你可以使用一个小技巧
定义一个boolean字段,像这样使用:

  @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (motionEvent.getAction() & MotionEvent.ACTION_MASK) { case MotionEvent.ACTION_DOWN: shouldClick = true; . . break; case MotionEvent.ACTION_UP: if (shouldClick) view.performClick(); break; case MotionEvent.ACTION_POINTER_DOWN: break; case MotionEvent.ACTION_POINTER_UP: break; case MotionEvent.ACTION_MOVE: //Do your stuff shouldClick = false; break; } rootLayout.invalidate(); return true; } 

我想你在你的OnTouchListener返回true 这将消耗事件,所以它不会被发送下来的任何进一步处理。

在旁注中,点击和触摸监听器有什么意义?

您应该在OnTouchListener返回false,然后您的OnClickListener也将被处理。

 button.setOnTouchListener(this); 

在这里实现接口和代码:

 @Override public boolean onTouch(View view, MotionEvent motionEvent) { switch (view.getId()) { case R.id.send: switch(motionEvent.getAction()){ case MotionEvent.ACTION_DOWN: //when the user has pressed the button //do the needful here break; case MotionEvent.ACTION_UP: //when the user releases the button //do the needful here break; } break; } return false; } 

为了在gridview中使这两个事件成为可能,只有通过如下返回监听器“false”,这对我才有效。

 **GridView myView = findViewById(R.id.grid_view); myView.setOnTouchListener(new OnTouchListener() { public boolean onTouch(View v, MotionEvent event) { // ... Respond to touch events return false; } });** 

通过这种方式可以实现这两个事件