如何在textViews上显示链接并能正确处理它们?
如何在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 ClassspanClass = 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; } }
在上述代码中,我们创建了一个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"属性来指定您想要的颜色值。