【问题标题】:Clickable links and copy/paste menu in EditView in androidandroid中EditView中的可点击链接和复制/粘贴菜单
【发布时间】:2013-12-05 19:57:37
【问题描述】:

我的 Android 应用中有一个 EditText 视图。我需要其中的“内部链接”,这意味着我需要一些按钮或在EditText 内跨度,并且使用onClick 到这个按钮我可以执行一些操作(而不是重定向到网页)。 我用ClickableSpan()这样实现了这个按钮

linkWord = "my link";
link = new SpannableString(linkWord);
cs = new ClickableSpan(){
private String w = linkWord;
    @Override
    public void onClick(View widget) {
    wrd.setText(w);
    }
};
link.setSpan(cs, 0, linkWord.length(), 0);
et.append(link);

为了使这个跨度可点击,我使用了

et.setMovementMethod(LinkMovementMethod.getInstance());

“内部链接”工作正常,但在使用et.setMovementMethod() 后,OnLongClick 菜单上的复制和粘贴项目被禁用。这是一个问题,因为我需要EditText 中的“链接”并同时从该视图复制文本。

我的想法是在监听器OnLongClickListener 中设置类似removeMovementMethod() 的东西来临时禁用“链接”功能并使用带有复制/粘贴的菜单,并在处理文本后再次打开setMovementMethod() 方法。但我不知道如何实现这一点。

你能帮帮我吗?您可能还有其他方法...

谢谢!

【问题讨论】:

    标签: android hyperlink copy android-edittext


    【解决方案1】:

    我认为让用户在链接和复制模式之间切换不会为您赢得可用性奖。我的解决方案允许您选择文本并同时打开链接。为了实现这一点,我简单地扩展了允许选择文本的 ArrowKeyMovementMethod,并从处理链接的点击/触摸的 LinkMovementMethod 添加了 onTouchEvent() 方法。只有一行代码需要更改,即在屏幕被触摸的坐标处找不到链接时从 TextView 中删除选择的代码。

    这是完整的课程:

    public class MyMovementMethod extends ArrowKeyMovementMethod {
    
        private static MyMovementMethod sInstance;
    
        public static MovementMethod getInstance() {
            if (sInstance == null) {
                sInstance = new MyMovementMethod ();
            }
            return sInstance;
        }
    
        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer, MotionEvent event) {
            int action = event.getAction();
    
            if (action == MotionEvent.ACTION_UP ||
                action == MotionEvent.ACTION_DOWN) {
                int x = (int) event.getX();
                int y = (int) event.getY();
    
                x -= widget.getTotalPaddingLeft();
                y -= widget.getTotalPaddingTop();
    
                x += widget.getScrollX();
                y += widget.getScrollY();
    
                Layout layout = widget.getLayout();
                int line = layout.getLineForVertical(y);
                int off = layout.getOffsetForHorizontal(line, x);
    
                ClickableSpan[] link = buffer.getSpans(off, off, ClickableSpan.class);
    
                if (link.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                        link[0].onClick(widget);
                    }
                    else if (action == MotionEvent.ACTION_DOWN) {
                        Selection.setSelection(buffer, buffer.getSpanStart(link[0]), buffer.getSpanEnd(link[0]));
                    }
    
                    return true;
                }
                /*else {
                    that's the line we need to remove
                    Selection.removeSelection(buffer);
                }*/
            }
    
            return super.onTouchEvent(widget, buffer, event);
        }
    
    }
    

    即使文档说明,这样做也很安全:

    这个接口[MovementMethod]是供框架使用的; 它不应该由应用程序直接实现。 http://developer.android.com/reference/android/text/method/MovementMethod.html

    上面的代码扩展了一个文档类而不是实现接口。它所做的只是添加一个检查以查看是否点击了链接,否则使用超类方法。

    【讨论】:

      【解决方案2】:

      我解决了这个问题,也许这对某人来说会很有趣......

      对于我使用的 EditText 内的可点击链接

      et.setMovementMethod(LinkMovementMethod.getInstance());
      

      在这种情况下,在 longClick 菜单中没有复制/粘贴项目。 为了激活它们,我需要回到正常的 EditText 状态,我可以这样做:

      et.setMovementMethod(ArrowKeyMovementMethod.getInstance());
      

      此方法后链接不起作用,但出现正常的longClick菜单。

      因此我在上下文菜单中添加了新项目并在这两个选项之间切换:

      @Override
      public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) {
          if(et.getSelectionStart() == -1){ // in case of setMovementMethod(LinkMovementMethod.getInstance())
              menu.add(0, 1, 0, "Enable copy");
          }
          else{
              menu.add(0, 2, 0, "Enable links");
          }
      }
      @Override
      public boolean onContextItemSelected(MenuItem item) {
          switch (item.getItemId()) {
          case 1:
                et.setMovementMethod(ArrowKeyMovementMethod.getInstance());
                et.setSelection(0, 0);
                    //re-register EditText for context menu:
                unregisterForContextMenu(et);
                registerForContextMenu(et);
                break;
            case 2:
                et.setMovementMethod(LinkMovementMethod.getInstance());
                break;
            }
            return true;
        }
      

      我还为上下文菜单注册了 EditText:

      registerForContextMenu(et);
      

      希望这会对某人有所帮助!

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2014-11-29
        • 1970-01-01
        • 2014-06-30
        • 1970-01-01
        • 2022-06-13
        • 2015-10-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多