Android(安卓)TextView设置自动识别的超链接字体颜色,及自身点击事件无响应的解决办法
16lz
2022-05-05
前言
我们在给TextView设置超链接的时候,可能最简单的,Android已经给出了一个非常的简单的做法就是:
在xml中设置:
android:autoLink="web"
或者
//sp为SpannableStringLinkify.addLinks(sp, Linkify.WEB_URLS);
如何设置超链接颜色
上边如果设置,就可以完成基本功能,但是安装在不同的手机上,超链接的颜色都会不同,比如vivo的一个机子上是黑色的,显示的样式也不一样!
所以,这里只能使用URLSpan手动去匹配,并设置颜色:
//注意:不要在xml配置android:autoLink属性 SpannableString sp = new SpannableString(str); //这句很重要,也可以添加自定义正则表达式 Linkify.addLinks(sp, Linkify.WEB_URLS); //主要是获取span的位置 URLSpan[] spans = sp.getSpans(0, str.length(), URLSpan.class); //这里可以用过循环处理就可以动态实现文本颜色的差别化了 //设置高亮样式一 for (URLSpan span : spans) { sp.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.base_blue)), sp.getSpanStart(span), sp.getSpanEnd(span), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); } //SpannableString对象设置给TextView mTv.setText(sp); //设置TextView可点击 mTv.setMovementMethod(LinkMovementMethod.getInstance());
问题,textview点击事件失效
为什么会出现这样的问题,是因为LinkMovementMethod中onTouchEvent(MotionEvent event)
,在ACTION_UP
事件中,返回了true,表示这里已经消费了up事件,那么自然不会再响应它的点击事件!
所以,这里的解决方案:
我在stackoverflow上找到一个回答:listview-textview-with-linkmovementmethod-makes-list-item-unclickable
public class LinkTextView extends android.support.v7.widget.AppCompatTextView { boolean dontConsumeNonUrlClicks = true; boolean linkHit; public LinkTextView(Context context) { super(context); } public LinkTextView(Context context, AttributeSet attrs) { super(context, attrs); } public LinkTextView(Context context, AttributeSet attrs, int defStyleAttr) { super(context, attrs, defStyleAttr); } @Override public boolean onTouchEvent(MotionEvent event) { linkHit = false; boolean res = super.onTouchEvent(event); if (dontConsumeNonUrlClicks) return linkHit; return res; } public static class LocalLinkMovementMethod extends LinkMovementMethod { static LocalLinkMovementMethod sInstance; public static LocalLinkMovementMethod getInstance() { if (sInstance == null) sInstance = new LocalLinkMovementMethod(); 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])); } if (widget instanceof LinkTextView) { ((LinkTextView) widget).linkHit = true; } return true; } else { Selection.removeSelection(buffer); Touch.onTouchEvent(widget, buffer, event); return false; } } return Touch.onTouchEvent(widget, buffer, event); } }}
然后在使用的时候:
//设置TextView可点击,并且调用自定义的LinkMovementMethod,不是url,返回false,否则会消费掉点击事件mTv.setMovementMethod(LinkTextView.LocalLinkMovementMethod.getInstance());
首先我们自定义一个TextView,定义一个布尔值,是否点击了超链接,然后我们继承LinkMovementMethod
,在他的onTouchEvent
中,如果确实是点击的span,则将上边的属性置为true,然后在TextView的onTouchEvent中,返回这个属性即可!(如果点击的是超链接,return true,如果不是超链接,则return false,事件会继续往下分发,检查是否注册的有点击事件,而去响应点击事件!)
更多相关文章
- [置顶] 如何演示你的App?Android录制Gif动态图教程
- Android中的通知—Notification
- android:maxHeight,android:maxWidth失效
- 一步步探索学习Android(安卓)Touch事件分发传递机制(一)
- android之CalendarView日历视图
- 巧用布局文件实现Android中实现事件监听机制
- intellij idea 设置用真机测试android
- android Dependencies ,Private Libraries ,Referenced Libraries
- Flutter与Android的差异性