【问题标题】:Android - long pressing to open the context menu on a TextView also triggers an autoLink clickAndroid - 长按打开 TextView 上的上下文菜单也会触发自动链接点击
【发布时间】:2015-02-08 03:42:03
【问题描述】:

我有一个启动上下文菜单的 TextView:

textView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
            @Override
            public void onCreateContextMenu(ContextMenu contextMenu, 
                                            View view,
                                            ContextMenu.ContextMenuInfo contextMenuInfo) {
                // Do stuff... 
            }
        });

此文本视图还在其 XML 中设置了 android:autoLink="all" 属性。

现在,如果我将 TextView 的内容设置为 URL 并长按该 URL,上下文菜单首先出现,但当我抬起手指时,链接被按下并打开浏览器。

有没有办法让上下文菜单或长按消耗触摸事件,以便不点击链接?我考虑过覆盖 onTouch() 让 TextView 处理 ACTION_UP 事件,但我无法可靠地跟踪上下文菜单何时可见以阻止触摸事件。

【问题讨论】:

    标签: android textview long-press android-contextmenu autolink


    【解决方案1】:

    这对我来说似乎有些 hacky,但这是我能够在不直接处理 View 的触摸事件的情况下完成这项工作的唯一方法(这很可能是正确的方法)。

    如果上下文菜单打开,我们实际上是在更改 TextView 的 LinkMovementMethod,因此 up 操作不会触发链接。当上下文菜单关闭时,我们恢复LinkMovementMethod,以便正常点击链接按预期工作。

    调整你的onCreateContextMenu()方法如下:

    textView.setOnCreateContextMenuListener(new OnCreateContextMenuListener() {
            @Override
            public void onCreateContextMenu(ContextMenu menu,
                                            View view,
                                            ContextMenu.ContextMenuInfo info) {
                textView.setMovementMethod(ArrowKeyMovementMethod.getInstance());
                // Do stuff
            }
        });
    

    然后像这样覆盖 Activity 的 onContextMenuClosed()

    @Override
    public void onContextMenuClosed(Menu menu)
    {
        textView.setMovementMethod(LinkMovementMethod.getInstance());
    }
    

    当然,这假设 textView 是您的 Activity 的类成员。

    【讨论】:

    • 不幸的是,在这种情况下,textView 是自定义视图的成员,该视图从 Activity 向下几个抽象层。依赖父活动通知视图似乎很麻烦,因此最好的方法可能是通过GestureDetectorOnLongClickListener 直接拦截触摸事件,并通过标志禁用ACTION_UP 事件,直到发生另一种类型的触摸事件。
    • @allenc 是的,处理触摸事件肯定是一个更可靠的解决方案。我想我读到你的问题是说你想避免这种情况。
    【解决方案2】:

    就像 Mike M. 所说的那样。

    您可以改用 setOnCreateContextMenuListener。并在此方法中执行单击父视图

    例子:

    这是视图组内的文本视图;

    textview.setOnCreateContextMenuListener(
    (menu, v, menuInfo) -> viewgroup.performLongClick());
    

    【讨论】:

      【解决方案3】:

      这个解决方案似乎没有任何缺点:

      override fun onCreateContextMenu(menu: ContextMenu, view: View, menuInfo: ContextMenuInfo) {
          // Inflate your menu, etc
      
          // ...
      
          // Cancel any tap in progress
          view.dispatchTouchEvent(MotionEvent.obtain(0, 0, MotionEvent.ACTION_CANCEL, 0f, 0f, 0))
      }
      

      长按将按预期显示上下文菜单,但当您抬起手指时不会发生任何事情(因为点击已被取消)。 导致上下文菜单的短按将照常处理。

      【讨论】:

        猜你喜欢
        • 2013-01-28
        • 2017-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-22
        • 1970-01-01
        相关资源
        最近更新 更多