6

EditText我在我的 Android 应用中有一个视图。我需要其中的“内部链接”,这意味着我需要一些按钮或跨越内部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()方法。但我不知道如何实现这一点。

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

谢谢!

4

2 回答 2

17

我不认为让用户在链接和复制模式之间切换会为你赢得可用性奖。我的解决方案允许您同时选择文本并打开链接。为了实现这一点,我简单地扩展了允许选择文本的 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

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

于 2013-08-30T21:49:46.040 回答
4

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

对于我使用的 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);

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

于 2012-05-14T14:34:01.333 回答