SpannableString

来源:互联网 发布:mac上的音频处理软件 编辑:程序博客网 时间:2024/06/15 18:40

效果图



SpanUtils.java

package com.ican.subjects.spannable_string.utils;import android.content.Context;import android.text.Spannable;import android.text.SpannableString;import android.text.TextPaint;import android.text.style.ClickableSpan;import android.text.style.ForegroundColorSpan;import android.view.View;import com.ican.subjects.spannable_string.bean.Topic;import com.ican.subjects.spannable_string.bean.User;import java.util.List;import java.util.regex.Matcher;import java.util.regex.Pattern;/** * Created by tuwenyuan on 2016/8/31.<br/> * 描述: * </br> */public class SpanUtils{    public static class PatternString{        /**         * #号括起来的话题#         */        public static final String TOPIC_PATTERN = "#[^#]+#";        /**         * 表情[大笑]         */        public static final String EXPRESSION_PATTERN = "\\[[^\\]]+\\]";        /**         * 网址         */        public static final String URL_PATTERN = "(([hH]ttp[s]{0,1}|ftp)://[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)|(www.[a-zA-Z0-9\\.\\-]+\\.([a-zA-Z]{2,4})(:\\d+)?(/[a-zA-Z0-9\\.\\-~!@#$%^&*+?:_/=<>]*)?)";    }    /**     *     * @param <T>     */    public interface SpanClickListener<T>{        void onSpanClick(T t);    }    /**     * 关键词变色处理     * @param str     * @param patterStr 需要变色的关键词 或者 正则表达式     * @return     */    public static SpannableString getKeyWordSpan(int color, String str, String patterStr) throws Exception {        SpannableString spannableString = new SpannableString(str);        Pattern patten = Pattern.compile(patterStr, Pattern.CASE_INSENSITIVE);        dealPattern(color, spannableString, patten, 0);        return spannableString;    }    /**     * 自动识别话题并做颜色处理,可点击     * @param color     * @param str     */    public static SpannableString getTopicSpan(int color, String str, boolean clickable, SpanClickListener spanClickListener, Topic topic) throws Exception {        SpannableString spannableString = new SpannableString(str);        Pattern patten = Pattern.compile(PatternString.TOPIC_PATTERN, Pattern.CASE_INSENSITIVE);        if(clickable){            dealClick(spannableString, patten, 0, spanClickListener, topic);        }        dealPattern(color, spannableString, patten, 0);        return spannableString;    }    /**     * @用户 颜色处理、点击处理     * @param color 前景色     * @param str     * @param clickable 是否可点击     * @param spanClickListener     * @param atUsers     * @return     * @throws Exception     */    public static SpannableString getAtUserSpan(int color, String str, boolean clickable, SpanClickListener spanClickListener, List<User> atUsers) throws Exception {        SpannableString spannableString = new SpannableString(str);        Pattern patten;        for (User u : atUsers) {            patten = Pattern.compile("@" + u.getName(), Pattern.CASE_INSENSITIVE);            if(clickable){                dealClick(spannableString, patten, 0, spanClickListener, u);            }            dealPattern(color, spannableString, patten, 0);        }        return spannableString;    }    /**     * 表情处理     * @param context     * @param str     * @return     */    public static SpannableString getExpressionSpan(Context context, String str) throws Exception {        return ExpressionConvertUtil.getInstace().getExpressionString(context, str);    }    /**     * 对spanableString进行正则判断,如果符合要求,则将内容变色     * @param color     * @param spannableString     * @param patten     * @param start     * @throws Exception     */    private static void dealPattern(int color, SpannableString spannableString, Pattern patten, int start) throws Exception {        Matcher matcher = patten.matcher(spannableString);        while (matcher.find()) {            String key = matcher.group();            // 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归            if (matcher.start() < start) {                continue;            }            // 计算该内容的长度,也就是要替换的字符串的长度            int end = matcher.start() + key.length();            //设置前景色span            spannableString.setSpan(new ForegroundColorSpan(color), matcher.start(), end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);            if (end < spannableString.length()) {                // 如果整个字符串还未验证完,则继续。。                dealPattern(color, spannableString, patten, end);            }            break;        }    }    /**     * 对spanableString进行正则判断,如果符合要求,将内容设置可点击     * @param spannableString     * @param patten     * @param start     * @param spanClickListener     * @param bean     */    private static void dealClick(SpannableString spannableString, Pattern patten, int start, final SpanClickListener spanClickListener, final Object bean){        Matcher matcher = patten.matcher(spannableString);        while (matcher.find()) {            String key = matcher.group();            // 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归            if (matcher.start() < start) {                continue;            }            // 计算该内容的长度,也就是要替换的字符串的长度            int end = matcher.start() + key.length();            spannableString.setSpan(new ClickableSpan() {                @Override                public void onClick(View widget) {                    spanClickListener.onSpanClick(bean);                }                @Override                public void updateDrawState(TextPaint ds) {                    super.updateDrawState(ds);                    //设置画笔属性                    ds.setUnderlineText(false);//默认有下划线                }            }, matcher.start(), end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);            if (end < spannableString.length()) {                // 如果整个字符串还未验证完,则继续。。                dealClick(spannableString, patten, end, spanClickListener, bean);            }            break;        }    }}

SpannableStringActivity.java

package com.ican.subjects.spannable_string;import android.graphics.Color;import android.text.SpannableString;import android.text.method.LinkMovementMethod;import android.widget.TextView;import android.widget.Toast;import com.ican.subjects.R;import com.ican.subjects.base.BaseActivity;import com.ican.subjects.spannable_string.bean.Topic;import com.ican.subjects.spannable_string.bean.User;import com.ican.subjects.spannable_string.utils.SpanUtils;import java.util.ArrayList;import java.util.List;/** * 创建者     涂文远 * 创建时间   2016/10/7 10:34 * 描述      ${TODO} * <p/> * 更新者     $Author$ * 更新时间   $Date$ * 更新描述   ${TODO} */public class SpannableStringActivity extends BaseActivity {    private TextView tvColoredKeywd;    private TextView tvTopic;    private TextView tvTestAt;    private TextView tvExpression;    @Override    public int getLayout() {        return R.layout.activity_spannable_string;    }    @Override    protected void initView() {        tvColoredKeywd = (TextView) findViewById(R.id.tv_keyword_colored);        tvTopic = (TextView) findViewById(R.id.tv_topic);        tvTestAt = (TextView) findViewById(R.id.tv_test_at);        tvExpression = (TextView) findViewById(R.id.tv_text_expression);    }    @Override    protected void initData() {        testColoredKeywd();        testTopic();        textAtUsers();        textExpression();    }    /**     * 关键字变色     */    private void testColoredKeywd() {        String string = "Android一词的本义指“机器人”,同时也是Google于2007年11月5日,Android logo相关图片,Android logo相关图片(36张)\n";        SpannableString cardText = null;        try {            cardText = SpanUtils.getKeyWordSpan(getResources().getColor(R.color.md_green_600), string, "Android");        } catch (Exception e) {            e.printStackTrace();        }        tvColoredKeywd.setText(cardText);    }    /**     * 测试话题     */    private void testTopic() {        String topic = "#舌尖上的大连#四种金牌烤芝士吃法爱吃芝士的盆友不要错过了~L秒拍视频\n";        SpannableString topicText = null;        try {            topicText = SpanUtils.getTopicSpan(Color.BLUE, topic, true, new SpanUtils.SpanClickListener<Topic>() {                @Override                public void onSpanClick(Topic t) {                    Toast.makeText(SpannableStringActivity.this, "点击话题:" + t.toString() , Toast.LENGTH_SHORT).show();                }            }, new Topic(1, "舌尖上的大连"));        } catch (Exception e) {            e.printStackTrace();        }        tvTopic.setText(topicText);        //如果想实现点击,必须要设置这个        tvTopic.setMovementMethod(LinkMovementMethod.getInstance());    }    /**     * 测试@好友     */    private void textAtUsers(){        List<User> users = new ArrayList<>();        users.add(new User(1, "好友1"));        users.add(new User(2, "好友2"));        StringBuilder sb = new StringBuilder("快来看看啊");        for (User u : users) {            sb.append("@").append(u.getName());        }        sb.append("\n");        try {            SpannableString atSpan = SpanUtils.getAtUserSpan(Color.BLUE, sb.toString(), true, new SpanUtils.SpanClickListener<User>() {                @Override                public void onSpanClick(User user) {                    Toast.makeText(SpannableStringActivity.this, "@好友:" + user.toString(), Toast.LENGTH_SHORT).show();                }            }, users);            tvTestAt.setText(atSpan);            tvTestAt.setMovementMethod(LinkMovementMethod.getInstance());        } catch (Exception e) {            e.printStackTrace();        }    }    /**     * 测试表情显示     */    private void textExpression(){        String exStr = "今天天气很好啊[呲牙],是不是应该做点什么[色]";        SpannableString span = null;        try {            span = SpanUtils.getExpressionSpan(this, exStr);        } catch (Exception e) {            e.printStackTrace();        }        tvExpression.setText(span);    }    private void initViews() {        tvColoredKeywd = (TextView) findViewById(R.id.tv_keyword_colored);        tvTopic = (TextView) findViewById(R.id.tv_topic);        tvTestAt = (TextView) findViewById(R.id.tv_test_at);        tvExpression = (TextView) findViewById(R.id.tv_text_expression);    }}

activity_spannable_string.xml

<?xml version="1.0" encoding="utf-8"?><ScrollView xmlns:android="http://schemas.android.com/apk/res/android"            xmlns:tools="http://schemas.android.com/tools"            android:layout_width="match_parent"            android:layout_height="match_parent"            android:paddingBottom="@dimen/activity_vertical_margin"            android:paddingLeft="@dimen/activity_horizontal_margin"            android:paddingRight="@dimen/activity_horizontal_margin"            android:paddingTop="@dimen/activity_vertical_margin"            android:background="#fff">    <LinearLayout        android:layout_width="match_parent"        android:layout_height="match_parent"        android:orientation="vertical">        <TextView            android:id="@+id/tv_keyword_colored"            android:layout_width="match_parent"            android:layout_height="wrap_content" />        <TextView            android:id="@+id/tv_topic"            android:layout_width="match_parent"            android:layout_height="wrap_content"        />        <TextView            android:id="@+id/tv_test_at"            android:layout_width="match_parent"            android:layout_height="wrap_content"        />        <TextView            android:id="@+id/tv_text_expression"            android:layout_width="match_parent"            android:layout_height="wrap_content" />    </LinearLayout></ScrollView>





0 0
原创粉丝点击