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

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

(0)

相关推荐

  • Android中TextView自动识别url且实现点击跳转

    前言 在项目中要在展示展示的文字中,自动匹配url 并且点击实现跳转,看了很多第三方的感觉都很复杂.后来自己写了一个简单的. 实现代码如下 1.创建一个继承UITextView的CjTextView . import <UIKit/UIKit.h> @interface CjTextView : UITextView @end import "CjTextView.h" @interface CjTextView () @property (nonatomic, copy

  • 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}\

  • Android studio点击跳转WebView详解

    本文实例为大家分享了Android studio点击跳转WebView的具体代码,供大家参考,具体内容如下 代码文件 import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.View; import android.webkit.WebView; import android.webkit.WebViewClient; import android.widget.

  • Android实现Activity、Service与Broadcaster三大组件之间互相调用的方法详解

    本文实例讲述了Android实现Activity.Service与Broadcaster三大组件之间互相调用的方法.分享给大家供大家参考,具体如下: 我们研究两个问题, 1.Service如何通过Broadcaster更改activity的一个TextView. (研究这个问题,考虑到Service从服务器端获得消息之后,将msg返回给activity) 2.Activity如何通过Binder调用Service的一个方法. (研究这个问题,考虑到与服务器端交互的动作,打包至Service,Ac

  • Android编程使用加速度传感器实现摇一摇功能及优化的方法详解

    本文实例讲述了Android编程使用加速度传感器实现摇一摇功能及优化的方法.分享给大家供大家参考,具体如下: 目前很多应用已经实现了摇一摇功能,这里通过讲解该功能的原理及实现回顾一下加速度传感器的使用: 1.首先获得传感器管理器的实例 sensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE); 2.通过传感器管理器获得加速传感器 accelerateSensor = getSensorMana

  • setcookie中Cannot modify header information-headers already sent by错误的解决方法详解

    复制代码 代码如下: <?php   setcookie("username","bu",time()+3600);   echo "aaaaa";?> 运行有警告Warning: Cannot modify header information - headers already sent by  下面是别人建议 方法一:在PHP里Cookie的使用是有一些限制的.1.使用setcookie必须在<html>标签之前2.

  • echarts中X轴显示特定个数label并修改样式的方法详解

    目录 前言 需求: 必须显示起始日期和终止日期 需求: 由于画布限制,只让显示起始和终止日期,或者再加上中间日期 需求: 将起始和终止刻度限定在轴线范围内,不允许现实超过轴线 总结 前言 在使用echarts绘图时可能遇到一些特别的需求,如,当x周表示日期且数据较多(如三个月,按天统计),此时如果按照echarts的默认配置,则会根据空间剩余的大小自动计算最终显示有限的几个不重叠的label 需求: 必须显示起始日期和终止日期 echarts默认属性会导致如果重叠,最大值和最小值会被隐藏,首先要

  • Java中统计字符个数以及反序非相同字符的方法详解

    复制代码 代码如下: import java.util.ArrayList;import java.util.List;public class Test2 { /**  * @param args  */ public static void main(String[] args) {  String src = "A B C D E B C";  //替换掉空格  src = src.replaceAll(" ", "") ; System.

  • 在Android TextView中显示图片的4种方式详解

    我们知道,TextView控件一般是用来显示文本的,而图片一般是用ImageView控件来显示. 那TextView能否显示图片呢?答案是肯定的!下面列出常见的4种方式. 1.XML文件中指定属性值 这种方式应该是最常用的了,在TextView的左上右下显示图片,可用  android:drawableLeft  android:drawableTop  android:drawableRight  android:drawableBottom 比如我们要在TextView的顶部设置图片,代码如

  • Android TextView中部分文字高亮显示

    Android  TextView中部分文字高亮显示 /** * 关键字高亮显示 * * @param context 上下文 * @param text 需要显示的文字 * @param target 需要高亮的关键字 * @param color 高亮颜色 * @param start 头部增加高亮文字个数 * @param end 尾部增加高亮文字个数 * @return 处理完后的结果 */ public static SpannableString highlight(Context

  • Android TextView中文字通过SpannableString设置属性用法示例

    本文实例讲述了Android TextView中文字通过SpannableString设置属性的方法.分享给大家供大家参考,具体如下: 在Android中,TextView是我们最常用的用来显示文本的控件. 一般情况下,TextView中的文本都是一个样式.那么如何对于TextView中各个部分的文本来设置字体,大小,颜色,样式,以及超级链接等属性呢?下面我们通过SpannableString的具体实例操作来演示一下. //创建一个 SpannableString对象 SpannableStri

随机推荐