如何让 onTouchEvent、长按和上下文菜单协同工作?
Posted
技术标签:
【中文标题】如何让 onTouchEvent、长按和上下文菜单协同工作?【英文标题】:How to get onTouchEvent, long click and context menu working together? 【发布时间】:2011-09-04 23:06:54 【问题描述】:在我们的应用程序中,我们有一个自定义视图(扩展ImageView
),我们在其中处理触摸事件以记录数据。我想在这个视图中添加上下文菜单功能,并遵循官方 android 文档中的指南。
onTouchEvent
代码本身可以正常工作。上下文菜单代码也可以正常工作。但是,如果我同时添加它们,上下文菜单代码将停止工作。我发现添加了两段代码后,onCreateContextMenu
永远不会被调用,因此上下文菜单永远不会显示。
根据我对Android文档的解释,从onTouchEvent
返回false
表示该事件没有被消费,所以应该使用它做进一步处理。出于某种原因,这里没有发生。如果有人能告诉我我错过了什么,我将不胜感激。顺便说一句,目标是运行 2.3.4 ROM 的 Nexus One。
这是自定义视图中onTouchEvent
的代码:
public boolean onTouchEvent(MotionEvent event)
switch (event.getAction())
case MotionEvent.ACTION_DOWN:
// Add event coordinates to an arraylist
break;
return false;
提前感谢您的帮助。
【问题讨论】:
能不能也贴一下longclick代码? 您的意思是我根据 Snicolas 的评论尝试的代码?很简单:@Override public boolean onLongClick(View v) openContextMenu(myView); return true;
【参考方案1】:
详细说明 hackbod 答案,您可能应该将return super.onTouchEvent(event);
作为最后一个方法声明。
我猜如果你不处理这个事件,如果你不调用默认的 View 行为,那么没有人会做任何事情,什么都不会发生。
返回值的点可能是例如调用某些祖先的默认行为,并让派生类知道祖先是否处理了事件。
在 Android Developers 上做了一些搜索后,参考主题 override an existing callback method for View here 它说:
这允许您为自定义视图中的每个事件定义默认行为,并确定是否应将事件传递给其他子视图。
因此,返回值背后的主要思想是让 Android 知道是否应该将事件传递给子 View。
HTH
编辑:
关于您在评论中提到的“方向”,一般来说(即不仅在 Android 上)UI 事件处理过程是这样的:
在某些时候,您的派生自定义控件会收到该事件。在您的事件挂钩实现中,是否涉及您的祖先的行为取决于您。这就是关于类继承方向的全部内容。
然后,还有另一个方向,与 UI 控件层次结构相关的方向。您的自定义控件可能包含在一个更大的控件容器中,您的控件也可能包含其他内部控件(文本框、按钮等)。关于这个方向,如果您声明不处理事件(返回 false),那么 UI 事件处理机制会将存储桶传递给 包含 (?) 控件(想想你的后台那个) .
【讨论】:
是的,hackbod 的建议效果很好。我试图了解它是如何工作的。我读了你的链接和Handling UI events subtopic。那里说“[...] 首先调用事件处理程序,然后从类定义中调用适当的默认处理程序”。现在我对 UI 事件的发展方向感到困惑:第一个文档提到子视图,而这个文档说“首先是事件处理程序,其次是默认处理程序”。看来我需要一个很好的教程来解释这种机制是如何工作的。你会碰巧有一个链接吗? 不,对不起,我没有这样的链接。但我编辑了我的答案,并试图澄清我对你提到的方向的想法。 非常感谢您的详细回复,非常感谢。如果您不介意,我还有一个问题:在您的编辑中,您提到调用祖先行为和事件处理机制,将消息传递给包含控件。这一切都说得通。在原始回复中,您引用了 Android 文档 w.r.t 将事件传递给子视图。我现在想要掌握的是其他子视图(谁的孩子,顺便说一句?)如何从我的控制中接收事件。事件是否会传递给父级,然后父级会通知其所有其他子视图有关此事件? 您是否要向上类层次调用默认行为,这取决于您的派生类实现。如果您声明不使用它,则可能接收事件的其他视图是与您的视图相关的视图,具体取决于 UI 层次结构,即 XML 布局中定义的层次结构。在这种情况下,子关系或父关系与类继承无关,而是指容器/包含控制关系。喜欢<LinearLayout><EditText /><Button /><CustomControl /></LinearLayout>
再次感谢您的帮助。我了解类层次结构部分。让我看看我是否使用您的示例正确理解了 UI 层次结构部分:如果我在 CustomControl
中收到一个触摸事件并返回 false 表示我没有使用它,LinearLayout
是否得到它并通知 EditText
和/或Button
?作为一个仅供参考,在我的特殊情况下,它是MyImageView extends ImageView
,我试图通过ImageView
的实现获得长点击-> 上下文菜单功能,同时通过MyImageView
类跟踪触摸事件。
【参考方案2】:
你可以从你的长按监听器中调用,
openContextMenu(View view)
http://developer.android.com/reference/android/app/Activity.html#openContextMenu(android.view.View)
【讨论】:
是的,但只要有onTouchEvent
代码,就不会调用长按监听器。【参考方案3】:
不要在OnCreate()
注册上下文菜单,在onTouch()
之前注册
返回真;
registerForContextMenu(View v);
openContextMenu(View v);
return true;
【讨论】:
【参考方案4】:返回 false 告诉父级您没有使用该事件。 View 的默认实现为该视图实现触摸处理;如果你想让它执行,你必须调用 super.onTouchEvent(event);
【讨论】:
感谢您的回复。你能澄清一下“视图的默认实现为该视图实现触摸处理”吗?你的意思是即使我返回false
,父级的触摸处理代码也不会运行?如果是这样,onTouchEvent
中的返回值有什么意义?【参考方案5】:
我最近遇到了类似的问题。当我在RecyeclerView
的孩子中启用长点击时,RecyclerView
的onTouchEvent
中无法接收到ACTION_DOWN
事件。
如果我改为RecyclerView
的dispatchTouchEvent
,我会工作。可以接收ACTION_DOWN
事件。
【讨论】:
以上是关于如何让 onTouchEvent、长按和上下文菜单协同工作?的主要内容,如果未能解决你的问题,请参考以下文章