如何在textViews上显示链接并能正确处理它们?

8 浏览
0 Comments

如何在textViews上显示链接并能正确处理它们?

背景

在你说这是一个转贴之前,我必须说我已经试过阅读其他帖子了,所以请继续阅读。

在textView中显示链接的基本方法可以通过以下方式完成:

final Spanned text = Html.fromHtml(getString(R.string.test));
textView.setText(text);
textView.setMovementMethod(LinkMovementMethod.getInstance());

而string.xml文件中可以包含以下内容:


a
        test
        ]]>
    

然而,我们可能想要捕获点击链接的事件,并自行处理。不仅如此,链接可能不需要是一个真实的URL。

有很多帖子展示了如何做到这一点,但我尝试过的帖子都处理得不好。

有些让intent在应用程序中处理,这相当麻烦,可能意味着其他应用程序也可以处理它(对吗?)而且我认为它要求链接是特定模式的。

有些让LinkMovementMethod来处理,但破坏了链接的可点击效果。有些说要改变颜色,但那不一样。

问题

你如何简单地为textview添加一个监听器,以便告诉你点击了其中的哪个文本区域?

我尝试过的

目前,我使用了LinkMovementMethod。我的代码存在以下问题:

  • 因为我不知道如何模拟点击普通链接,所以当你点击它时,它看起来很奇怪。背景看起来不对,我认为我需要使用设备的默认背景,但找不到如何做到。与一些人可能说的不同,不是通过使用以下代码:

textview.getLinkTextColors().getDefaultColor()

  • 在某些情况下,文本可能会保持点击状态。

以下是代码:

MainActivity.java(使用示例)

public class MainActivity extends Activity {
    @Override
    public void onCreate(final Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        final String a = "aaaa123456bbbb7890";
        final TextView textView = (TextView) findViewById(R.id.span);
        textView.setText(Html.fromHtml(a));
        final LinkClickMovementMethodExt linkMovementMethod = new LinkClickMovementMethodExt();
        linkMovementMethod.setOnLinkClickedListener(new OnLinkClickedListener() {
            @Override
            public void onLinkClicked(final TextView clickedTextView, final URLSpan clickedSpan) {
                Toast.makeText(MainActivity.this, clickedSpan.getURL(), Toast.LENGTH_SHORT).show();
            }
        });
        textView.setMovementMethod(linkMovementMethod);
    }
}

LinkClickMovementMethodExt.java

/** 用于处理点击textViews链接的类。基于http://stackoverflow.com/a/16182500/878126 */
public class LinkClickMovementMethodExt extends LinkMovementMethod {
    // TODO 检查如何获取点击链接的默认背景
    private final BackgroundColorSpan LINK_COLOR = new BackgroundColorSpan(0xFFACE0F4);
    private final Class spanClass = URLSpan.class;
    private OnLinkClickedListener mOnLinkClickedListener;
    public interface OnLinkClickedListener {
        public void onLinkClicked(TextView textView, URLSpan clickedSpan);
    }
    @Override
    public boolean onTouchEvent(final TextView textView, final Spannable buffer, final MotionEvent event) {
        final int action = event.getAction();
        if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
            int x = (int) event.getX();
            int y = (int) event.getY();
            x -= textView.getTotalPaddingLeft();
            y -= textView.getTotalPaddingTop();
            x += textView.getScrollX();
            y += textView.getScrollY();
            final Layout layout = textView.getLayout();
            final int line = layout.getLineForVertical(y);
            final int off = layout.getOffsetForHorizontal(line, x);
            /**
             * 获取感兴趣的span
             */
            final Object[] spans = buffer.getSpans(off, off, spanClass);
            if (spans.length != 0) {
                if (action == MotionEvent.ACTION_DOWN) {
                    Selection.setSelection(buffer, buffer.getSpanStart(spans[0]), buffer.getSpanEnd(spans[0]));
                    for (final Object span : spans) {
                        if (span instanceof URLSpan) {
                            final int start = Selection.getSelectionStart(textView.getText());
                            final int end = Selection.getSelectionEnd(textView.getText());
                            final Spannable selectedSpan = (Spannable) textView.getText();
                            selectedSpan.setSpan(LINK_COLOR, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                            textView.setText(selectedSpan);
                            if (mOnLinkClickedListener != null)
                                mOnLinkClickedListener.onLinkClicked(textView, (URLSpan) span);
                        }
                    }
                    return false;
                } else if (action == MotionEvent.ACTION_UP) {
                    final Spannable span = (Spannable) textView.getText();
                    span.removeSpan(LINK_COLOR);
                    textView.setText(span);
                    return false;
                }
            }
        }
        return super.onTouchEvent(textView, buffer, event);
    }
    @Override
    public boolean canSelectArbitrarily() {
        return true;
    }
    @Override
    public boolean onKeyUp(final TextView widget, final Spannable buffer, final int keyCode, final KeyEvent event) {
        return false;
    }
    public void setOnLinkClickedListener(final OnLinkClickedListener onLinkClickedListener) {
        this.mOnLinkClickedListener = onLinkClickedListener;
    }
}

0
0 Comments

在上述代码中,我们创建了一个TextView,并通过设置android:linksClickable="true"属性来使文本中的链接可点击。接下来,在Java代码中,我们通过调用tvmsg.setMovementMethod(LinkMovementMethod.getInstance())方法来设置TextView的移动方法为LinkMovementMethod,这样就可以处理链接的点击事件。然后,我们使用tvmsg.setText(Html.fromHtml(message))方法将文本内容设置为Html格式的文本。

要处理链接的点击事件并自己处理它,我们可以在Java代码中为TextView设置一个点击监听器。例如:

tvmsg.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        // 处理链接的点击事件
    }
});

这样,当链接被点击时,点击监听器中的onClick方法将被调用,您可以在其中编写您自己的处理逻辑。

关于为什么更改了"textColorLink",这是因为在代码中我们使用了Html.fromHtml(message)来设置TextView的文本内容,其中的链接默认会以“#EE4E1D”颜色显示。如果您想改变链接的颜色,您可以在XML中通过设置"textColorLink"属性来指定您想要的颜色值。

0