android TextView中识别多个url并分别点击跳转方法详解
作者:茕&茕 发布时间:2023-06-21 04:42:32
标签:android,TextView,url
实现方案:
我们直接参考实例代码:
private String pattern =
"((http|ftp|https)://)(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?|(([a-zA-Z0-9\\._-]+\\.[a-zA-Z]{2,6})|([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}))(:[0-9]{1,4})*(/[a-zA-Z0-9\\&%_\\./-~-]*)?";
Pattern r = Pattern.compile(pattern);
Matcher m;
mTv.setText(identifyUrl(richURL.msg));
public SpannableStringBuilderForAllvers identifyUrl(CharSequence text) {
CharSequence contextText;
CharSequence clickText;
text = text == null ? "" : text;
//以下用于拼接本来存在的spanText
SpannableStringBuilderForAllvers span = new SpannableStringBuilderForAllvers(text);
ClickableSpan[] clickableSpans = span.getSpans(0, text.length(), ClickableSpan.class);
if (clickableSpans.length > 0) {
int start = 0;
int end = 0;
for (int i = 0; i < clickableSpans.length; i++) {
start = span.getSpanStart(clickableSpans[0]);
end = span.getSpanEnd(clickableSpans[i]);
}
//可点击文本后面的内容页
contextText = text.subSequence(end, text.length());
//可点击文本
clickText = text.subSequence(start, end);
} else {
contextText = text;
clickText = null;
}
m = r.matcher(contextText);
//匹配成功
while (m.find()) {
//得到网址数m.group()
if (m.start() < m.end()) {
span.setSpan(new LinkClickSpan(m.group(), m.group(), mUrlSpanClickListener),
m.start(), m.end(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
}
return span;
}
private static final String HTTPS = "https://";
private static final String HTTP = "http://";
private static final String FTP = "ftp://";
public static boolean hasNetUrlHead(String url) {
return (!TextUtils.isEmpty(url)) && (url.startsWith(HTTP) || url.startsWith(HTTPS) || url.startsWith(FTP));
}
private UrlSpanClickListener mUrlSpanClickListener = new UrlSpanClickListener() {
@Override
public void onClick(View view, String url, String content) {
if (TextUtils.isEmpty(url)) {
return;
}
Matcher url_matcher = Patterns.WEB_URL.matcher(url);
if (url_matcher.matches()) {
String tempUrl;
if (hasNetUrlHead(url)) {
tempUrl = url;
} else {
tempUrl = HTTPS + url;
}
//通过webview打开相应的url
//Bundle bundle = new Bundle();
//bundle.putString(WebCordovaBaseFragment.EXTRA_URL, tempUrl);
//bundle.putBoolean(WebCordovaBaseFragment.ENABLE_WEB_TITLE, true);
//WebViewActivity.presentWeb(Utilities.getApplicationContext(), WebViewActivity.class, WebCommonFragment.class, content, bundle);
}
}
};
public interface UrlSpanClickListener {
void onClick(View view, String url, String content);
}
public static class LinkClickSpan extends ClickableSpan {
private int mColor = Utilities.getApplicationContext().getResources().getColor(R.color.yc_color_007AFF_CBN);
private String mUrl;
private String mContent;
UrlSpanClickListener mClickListener;
public LinkClickSpan(String url, String content, UrlSpanClickListener onClickListener) {
super();
mUrl = url;
mContent = content;
mClickListener = onClickListener;
}
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(mColor);
ds.linkColor = mColor;
ds.setUnderlineText(true);//设置是否下划线
ds.clearShadowLayer();
}
@Override
public void onClick(View widget) {
if (mClickListener != null) {
mClickListener.onClick(widget, mUrl, mContent);
}
}
}
public class SpannableStringBuilderForAllvers extends SpannableStringBuilder{
public SpannableStringBuilderForAllvers() {
super("");
}
public SpannableStringBuilderForAllvers(CharSequence text) {
super(text, 0, text.length());
}
public SpannableStringBuilderForAllvers(CharSequence text, int start, int end){
super(text,start,end);
}
@Override
public SpannableStringBuilder append(CharSequence text) {
if (text == null) {
return this;
}
int length = length();
return (SpannableStringBuilderForAllvers)replace(length, length, text, 0, text.length());
}
/**该方法在原API里面只支持API21或者以上,这里适应低版本*/
public SpannableStringBuilderForAllvers append(CharSequence text, Object what, int flags) {
if (text == null) {
return this;
}
int start = length();
append(text);
setSpan(what, start, length(), flags);
return this;
}
}
public class ClickableSpanTextView extends AppCompatTextView {
private BackgroundColorSpan backgroundColorSpan;
private boolean hasSpan;
public ClickableSpanTextView(Context context) {
super(context);
init();
}
public ClickableSpanTextView(Context context, AttributeSet attrs) {
super(context, attrs);
init();
}
public ClickableSpanTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
init();
}
private void init() {
setMovementMethod(LinkMovementMethod.getInstance());
backgroundColorSpan = new BackgroundColorSpan(getContext().getResources().getColor(R.color.yc_color_4B4B4B_CDG));
}
@Override
public boolean onTouchEvent(MotionEvent event) {
boolean handled = super.onTouchEvent(event);
int action = event.getAction();
if (!(getText() instanceof Spannable)) {
return handled;
}
Spannable spannable = (Spannable) getText();
if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
int x = (int) event.getX();
int y = (int) event.getY();
x -= getTotalPaddingLeft();
y -= getTotalPaddingTop();
x += getScrollX();
y += getScrollY();
Layout layout = getLayout();
int line = layout.getLineForVertical(y);
int off = layout.getOffsetForHorizontal(line, x);
if (off >= getText().length()) {
int off1 = layout.getOffsetForHorizontal(line, x - getTextSize());
if (off == off1) {
return handled;
}
}
ClickableSpan[] links = spannable.getSpans(off, off, ClickableSpan.class);
if (links.length > 0) {
ClickableSpan clickableSpan = links[0];
int start = spannable.getSpanStart(clickableSpan);
int end = spannable.getSpanEnd(clickableSpan);
if (action == MotionEvent.ACTION_DOWN && !hasSpan) {
spannable.setSpan(backgroundColorSpan, start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
hasSpan = true;
} else if (hasSpan) {
spannable.removeSpan(backgroundColorSpan);
hasSpan = false;
}
}
return links.length != 0;
} else {
if (hasSpan && action != MotionEvent.ACTION_MOVE) {
spannable.removeSpan(backgroundColorSpan);
hasSpan = false;
}
}
return handled;
}
}
以上实例代码大家可以测试下,感谢大家的学习。
来源:https://www.cnblogs.com/wangqiong/p/11412269.html
0
投稿
猜你喜欢
- 已知字符串“aabbbcddddeeffffghijklmnopqrst”编程找出出现最多的字符和次数,要求时间复杂度小于O(n^2)/**
- 最近没事写了一个简易浏览器,在刚开始写的时候遇到一些问题,主要的问题就是如何在自己的webview中显示所有的网页数据,不过不指
- 您已经看到很多包含视频内容的应用程序,比如带有视频教程的食谱应用程序、电影应用程序和体育相关的应用程序。您是否想知道如何将视频内容添加到您的
- 1: .net framework 由两个部分组成:CLR 和 FCL。2:在CLR中,所有错误都是通过异常来报告的。3:智能感知功能主要是
- 前言通过此篇文章,你将了解到:Flutter windows和Android桌面应用屏幕适配的解决方案;屏幕适配的相关知识和原理;flutt
- forward_list 概述forward_list 是 C++ 11 新增的容器,它的实现为单链表。forward_list 是支持从容
- 需求:有些时候,我们需要连接多个数据库,但是,在方法调用前并不知道到底是调用哪个。即同时保持多个数据库的连接,在方法中根据传入的参数来确定。
- SharedPreferences是Android中最容易理解的数据存储技术,实际上SharedPreferences处理的就是一个key-
- 因为mybatis好使,所以几乎需要操作数据库的时候,我都会使用mybatis,而且在一个正式的项目中,同时存在BS和CS的程序,都使用的M
- [LeetCode] 159. Longest Substring with At Most Two Distinct Characters
- 网络中数据传输经常是xml或者json,现在做的一个项目之前调其他系统接口都是返回的xml格式,刚刚遇到一个返回json格式数据的接口,通过
- 本文实例为大家分享了android自定义环形对比图的具体代码,供大家参考,具体内容如下1.首先在res/values里创建一个attr.xm
- 1、前言当提及如何终止一个线程时,部分读者通常立马想到的方法肯定是stop(),但是stop()方法并不被推荐使用(很多规范中是禁止使用的)
- 在实际开发中,我们经常会需要在页面跳转的时候携带路由参数,典型的例子就是从列表到详情页的时候,需要携带详情的 id,以便详情页获取对应的数据
- 目录Navigator 的 push 和 pop方法代码实现最终效果Navigator 的 push 和 pop方法Navigator 导航
- 参考:How to catch an Exception from a threadIs there a way to make Runna
- 关于UIToolbarToolBar工具栏是视图View的属性,可以在工具栏上添加工具栏按钮Bar Button Item(可以是自定义的C
- 在windows环境下,我们通常在IDE如VS的工程中开发C++项目,对于生成和使用静态库(*.lib)与动态库(*.dll)可能都已经比较
- flutter material widget组件之信息展示组件,供大家参考,具体内容如下widget分为两类:widgets librar
- UI 妹纸又给了个图叫我做,我一看是这样的:我们首先把这个控件划分成 几个部分:1.底下部分的直线 :2.左右两边的半圆