Android自动识别标签的自定义TextView(可自定义点击事件)

背景:

项目中要实现类似淘宝客服智能机器人,客服发送一段带有超链接的文字,例:"想知道印尼好吃的餐馆都在哪么,看看资讯列表你就知道啦,this is a good place to eat dinner with friend,也可以去百度获取最新相关资讯",显示在聊天页面,点击带有超链接的文字跳转到应用内指定页面或者打开网页.

实现方式参考了http://blog.csdn.net/lvshaorong/article/details/51767368写的博客,同时完善了该方法在列表中的问题,代码如下:



import android.content.Context;
import android.support.v7.widget.AppCompatTextView;
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 com.picc.aasipods.common.utils.UrlJumpUtil;
import com.picc.aasipods.module.xiaoi.controller.XiaoIChatActivity;

import java.util.ArrayList;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * author:zhangfeng on 2018/1/2.
 * desc:
 */

public class AlxUrlTextView extends AppCompatTextView {

    private XiaoIChatActivity mActivity;

    public AlxUrlTextView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public void setText(String text) {
        super.setText("");
        if (text == null || text.length() == 0) return;
        Object[][] output = getUrlFromJDP(text);
        int urlCount = 0;
        if (output == null || output.length == 0 || output[0] == null || output[0].length == 0) {
            super.setText(text);
            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];//标签在源字符串的起始位置
            int end = (int) output[3][i];//标签在源字符串的结束位置
            SpannableString spannableString = new SpannableString(blueText);
            spannableString.setSpan(new ClickableSpan() {
                //在这里定义点击下划线文字的点击事件,不一定非要打开浏览器
                @Override
                public void onClick(View widget) {
		//此处实现自己项目中的跳转逻辑
                    //UrlJumpUtil.instance(mActivity).jumpWithUrl(href);
                }

            }, 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 hosts = new ArrayList<>(4);
        ArrayList urls = new ArrayList<>(4);
        ArrayList starts = new ArrayList<>(4);
        ArrayList ends = new ArrayList<>(4);

        Pattern pattern = Pattern.compile("(.*?)");//首先将a标签分离出来
        Matcher matcher = pattern.matcher(source);
        int i = 0;
        while (matcher.find()) {
            String raw = matcher.group(0);
            Pattern url_pattern = Pattern.compile("");//将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是标签起始位置
        outputs[3] = ends.toArray(new Integer[ends.size()]);//下标3是标签结束位置
        return outputs;
    }
	//此处设置上下文环境
    public void setContext(XiaoIChatActivity activity) {
        this.mActivity = activity;
    }
}
2. 布局文件如下




    

    

        

        

        

            

            
        
    
3.聊天页面的适配器中调用

@Override
    public View getView(final int position, View convertView, ViewGroup parent) {
        
	...
        
        if (holder.mMsg != null) {
            holder.mMsg.setContext(this.activity);
            holder.mMsg.setText(chatMessage.getMsg()+"资讯列表");
        }
        
        ...
            
        return convertView;
    }

    public void setContext(XiaoIChatActivity activity) {
        this.activity = activity;
    }

    class ViewHolder {
        ...
AlxUrlTextView  mMsg;
... }
 
  




你可能感兴趣的:(android)