实现方案:

我们直接参考实例代码:

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;
  }
}

以上实例代码大家可以测试下,感谢大家的学习和对Devmax的支持。

android TextView中识别多个url并分别点击跳转方法详解的更多相关文章

  1. HTML5 播放 RTSP 视频的实例代码

    目前大多数网络摄像头都是通过 RTSP 协议传输视频流的,但是 HTML 并不标准支持 RTSP 流。本文重点给大家介绍HTML5 播放 RTSP 视频的实例代码,需要的朋友参考下吧

  2. 浅析HTML5中的download属性使用

    这篇文章主要介绍了浅析HTML5中的download属性使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  3. html5 canvas合成海报所遇问题及解决方案总结

    这篇文章主要介绍了html5 canvas合成海报所遇问题及解决方案总结,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  4. HTML5 Blob 实现文件下载功能的示例代码

    这篇文章主要介绍了HTML5 Blob 实现文件下载功能的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  5. Html5 video标签视频的最佳实践

    这篇文章主要介绍了Html5 video标签视频的最佳实践,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  6. web字体加载方案优化小结

    这篇文章主要介绍了web字体加载方案优化小结,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

  7. HTML5在微信内置浏览器下右上角菜单的调整字体导致页面显示错乱的问题

    HTML5在微信内置浏览器下,在右上角菜单的调整字体导致页面显示错乱的问题,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧

  8. ios – 在WKWebView中获取链接URL

    我想在WKWebView中获取tapped链接的url.链接采用自定义格式,可触发应用中的某些操作.例如HTTP://我的网站/帮助#深层链接对讲.我这样使用KVO:这在第一次点击链接时效果很好.但是,如果我连续两次点击相同的链接,它将不报告链接点击.是否有解决方法来解决这个问题,以便我可以检测每个点击并获取链接?任何关于这个的指针都会很棒!解决方法像这样更改addobserver在observeValue函数中,您可以获得两个值

  9. ios – containerURLForSecurityApplicationGroupIdentifier:在iPhone和Watch模拟器上给出不同的结果

    我使用默认的XCode模板创建了一个WatchKit应用程序.我向iOSTarget,WatchkitAppTarget和WatchkitAppExtensionTarget添加了应用程序组权利.(这是应用程序组名称:group.com.lombax.fiveminutes)然后,我尝试使用iOSApp和WatchKitExtension访问共享文件夹URL:延期:iOS应用:但是,测试NSURL

  10. ios – 加载空白页面的SFSafariViewController

    我正在使用SFSafariViewController在我的iOS应用程序中打开一个URL..它在iOS9上完美运行但在将我的设备更新到iOS10后,它只是在地址栏中加载了一个没有URL的空白页面.甚至safariViewController(控制器:SFSafariViewController,didCompleteInitialLoaddidLoadSuccessfully:Bool)在控制器

随机推荐

  1. Flutter 网络请求框架封装详解

    这篇文章主要介绍了Flutter 网络请求框架封装详解,小编觉得挺不错的,现在分享给大家,也给大家做个参考。一起跟随小编过来看看吧

  2. Android单选按钮RadioButton的使用详解

    今天小编就为大家分享一篇关于Android单选按钮RadioButton的使用详解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧

  3. 解决android studio 打包发现generate signed apk 消失不见问题

    这篇文章主要介绍了解决android studio 打包发现generate signed apk 消失不见问题,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧

  4. Android 实现自定义圆形listview功能的实例代码

    这篇文章主要介绍了Android 实现自定义圆形listview功能的实例代码,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  5. 详解Android studio 动态fragment的用法

    这篇文章主要介绍了Android studio 动态fragment的用法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  6. Android用RecyclerView实现图标拖拽排序以及增删管理

    这篇文章主要介绍了Android用RecyclerView实现图标拖拽排序以及增删管理的方法,帮助大家更好的理解和学习使用Android,感兴趣的朋友可以了解下

  7. Android notifyDataSetChanged() 动态更新ListView案例详解

    这篇文章主要介绍了Android notifyDataSetChanged() 动态更新ListView案例详解,本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下

  8. Android自定义View实现弹幕效果

    这篇文章主要为大家详细介绍了Android自定义View实现弹幕效果,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  9. Android自定义View实现跟随手指移动

    这篇文章主要为大家详细介绍了Android自定义View实现跟随手指移动,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  10. Android实现多点触摸操作

    这篇文章主要介绍了Android实现多点触摸操作,实现图片的放大、缩小和旋转等处理,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部