前言:

项目里遇到这样一个需求,服务器发来一个字符串如下xxxx<a href="http://www.baidu.com">baidu</a>xxxx,xxxx,需要在Android客户端上显示出来,并且点击相应的文字还能打开系统默认浏览器,大体效果如下图:


我的实现思路大体是这样:首先将带有<a>标签的字符串使用正则处理,将<a>标签中的href字段取出,显示文本取出,这个<a>标签在源字符串的起始位置和结束位置取出,用于替换相应文字。通过getUrlFromJDP()方法实现,并返回一个二位数组,这个二位数组的第二维是这段文字的url序号,第一维是url,显示文字,起始结束位置的下标。

将需要的字符串取出之后,通过SpannableString组合多个普通的span和可点击的span实现分段点击效果,并且点击事件可以自定义。

代码实现很简单,只有两个方法:

import android.content.Context;import android.content.Intent;import android.net.Uri;import android.text.SpannableString;import android.text.Spanned;import android.text.method.LinkMovementMethod;import android.text.style.ClickableSpan;import android.util.AttributeSet;import android.util.Log;import android.view.View;import android.widget.TextView;import java.util.ArrayList;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * Created by Administrator on 2016/6/22. */public class AlxUrlTextView extends TextView{    public AlxUrlTextView(Context context, AttributeSet attrs) {        super(context, attrs);    }    public void setText(String text){        if(text==null || text.length()==0)return;        Object[][] output = getUrlFromJDP(text);        int urlCount = 0;        if(output[0]==null || output[0].length==0)return;        urlCount = output[0].length;        Log.i("AlexUrl","一共有"+urlCount+"个url");        String remainText = text;        int lastStart = 0;//截取到一部分后截掉部分的长度        for(int i=0;i<urlCount;i++){            String blueText = (String) output[0][i];//带下划线的文字            final String href = (String) output[1][i];//下划线文字所对应的url连接            int start = (int) output[2][i];//<a>标签在源字符串的起始位置            int end = (int) output[3][i];//<a>标签在源字符串的结束位置            SpannableString spannableString = new SpannableString(blueText);            spannableString.setSpan(new ClickableSpan() {                //在这里定义点击下划线文字的点击事件,不一定非要打开浏览器                @Override                public void onClick(View widget) {                    //下面是打开系统默认浏览器的方法                    Intent intent = new Intent();                    intent.setAction("android.intent.action.VIEW");                    Uri content_url = Uri.parse(href);                    intent.setData(content_url);                    getContext().startActivity(intent);                }            },0,blueText.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);            int subStart = start - lastStart;            String front = remainText.substring(0,subStart);//截取出一段文字+一段url            Log.i("Alex","起始位置"+(end-lastStart));            remainText = remainText.substring(end-lastStart,remainText.length());//剩下的部分            lastStart = end;            Log.i("Alex","front是"+front);            Log.i("Alex","spann是"+spannableString);            Log.i("Alex","remain是"+remainText);            if(front.length()>0)append(front);            append(spannableString);        }        if(remainText!=null && remainText.length()>0)append(remainText);        setMovementMethod(LinkMovementMethod.getInstance());//响应点击事件    }    public static Object[][]  getUrlFromJDP(String source){        ArrayList<String> hosts = new ArrayList<>(4);        ArrayList<String> urls = new ArrayList<>(4);        ArrayList<Integer> starts = new ArrayList<>(4);        ArrayList<Integer> ends = new ArrayList<>(4);        Pattern pattern = Pattern.compile("<a href=\".*?\">(.*?)</a>");//首先将a标签分离出来        Matcher matcher = pattern.matcher(source);        int i=0;        while(matcher.find()){            String raw = matcher.group(0);            Pattern url_pattern = Pattern.compile("<a href=\"(.*?)\">");//将href分离出来            Matcher url_matcher = url_pattern.matcher(raw);            try {                if(url_matcher.find()){                    String url = url_matcher.group(1);                    Log.i("Alex","真实url是"+url);//括号里面的                    urls.add(i,url);                }            } catch (Exception e) {                e.printStackTrace();            }            String host = null;//将要显示的文字分离出来            try {                host = matcher.group(1);            } catch (Exception e) {                e.printStackTrace();                continue;            }            Log.i("Alex","蓝色文字是"+host);//括号里面的            hosts.add(i,host);            starts.add(i,matcher.start());            ends.add(i,matcher.end());            Log.i("Alex","字符串起始下标是"+matcher.start()+"结尾下标是"+matcher.end());//匹配出的字符串在源字符串的位置            i++;        }        if(hosts.size()==0){            Log.i("Alex","没有发现url");            return null;        }        Object[][] outputs = new Object[4][hosts.size()];//第一个下标是内容的分类,第二个下标是url的序号        outputs[0] = hosts.toArray(new String[hosts.size()]);//下标0是蓝色的文字        outputs[1] = urls.toArray(new String[urls.size()]);//下标1是url        outputs[2] = starts.toArray(new Integer[starts.size()]);//下标2是<a>标签起始位置        outputs[3] = ends.toArray(new Integer[ends.size()]);//下标3是<a>标签结束位置        return outputs;    }}

布局文件如下

<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:app="http://schemas.android.com/apk/res-auto"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    >    <TextView        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:text="Hello World!" />    <com.example.administrator.googleservicetest.AlxUrlTextView        android:id="@+id/tv_url"        android:text=""        android:textSize="22dp"        android:layout_centerHorizontal="true"        android:layout_centerVertical="true"        android:layout_width="wrap_content"        android:layout_height="wrap_content" /></RelativeLayout>

调用方法如下

 AlxUrlTextView textView = (AlxUrlTextView) findViewById(R.id.tv_url); textView.setText("想知道印尼好吃的餐馆都在哪么,看看<a href=\"http://www.qraved.com\">Qraved!</a>你就知道啦,this is a good place to eat dinner with friend,也可以去<a href=\"http://www.baidu.com\">百度</a>获取最新相关资讯");        


更多相关文章

  1. Android(安卓)EditText 限制只能输入指定范围的数字
  2. Android的文字渲染
  3. Android自定义View实现竖直跑马灯效果案例解析
  4. Android之讯飞语音-文字转语音(不用另外安装语音合成包apk)遇到的
  5. 跟Google学习Android开发-起始篇-构建你的第一个应用程序(3)
  6. Android字符串及字符串资源的格式化
  7. Android(安卓)Studio3.0开发JNI流程------JNI中字符串拼接的三种
  8. 实战:Android活动目录LiveFolder开发
  9. 完整的Android表情功能处理方案

随机推荐

  1. 【java】使用jwt进行认证授权
  2. 基于数据库实现分布式锁
  3. 【tomcat】使用jks配置https
  4. 基于单节点redis实现分布式锁
  5. 【springboot】使用redisson分布式锁
  6. 【redis】有关redis面试那些事(一)
  7. 【redis】使用redis位图轻松实时统计日活
  8. 5G消息要来了,你们期待吗?
  9. 【java】说说有关jdk动态代理的那些事
  10. 【mysql】ipv4地址转换为4字节整数