【问题标题】:How to get onTouchEvent, long click and context menu working together?如何让 onTouchEvent、长按和上下文菜单协同工作?
【发布时间】: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; }

标签: android contextmenu touch-event long-click


【解决方案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 的孩子中启用长点击时,RecyclerViewonTouchEvent 中无法接收到ACTION_DOWN 事件。

    如果我改为RecyclerViewdispatchTouchEvent,我会工作。可以接收ACTION_DOWN 事件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-05-04
      • 2010-11-24
      • 2020-01-17
      • 2017-11-15
      • 2020-01-13
      • 2014-11-12
      相关资源
      最近更新 更多