Android 仿微博@ # 艾特 话题功能

这里使用的是HTML格式

String str=张三占位符===占位符===占位符李四" +
"占位符===占位符===占位符吃蛇" +
"占位符===占位符===占位符王五

个人这里写的非常的差 希望各位大佬指点,然后解析的地方本人洗完各位自己重新写一个,这个解析并不是非常好,可以在找XML解析,其中个人建议自己写一个SAX解析会比较好一点
附上一个XML解析网页
这里是XML解析

Android 仿微博@ # 艾特 话题功能_第1张图片

本人是继承了一个TextView并在TextView中进行的处理


public class HtmlText extends TextView {

    private Context context;

    private String mData;


    //接口回调
    private OnHtmlTextClick mOnHtmlTextClick;
    //初始化接口回调
    public void setOnHtmlTextClick(OnHtmlTextClick mOnHtmlTextClick) {
        this.mOnHtmlTextClick = mOnHtmlTextClick;
    }

    //设置点击事件需要上下文
    public void init(Context context) {
        this.context = context;
    }

    public HtmlText(Context context) {
        super(context);
    }

    public HtmlText(Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
    }

    public HtmlText(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }


    @Override
    public void setText(CharSequence text, BufferType type) {
        //得到String字符
        if (text == null) {
            mData = "";
        } else {
            mData = text.toString();
        }
        /*用Html中重写的TagHandler解析,以Spanned格式输出,这里希望到时候大家更换一下或者自己写一个
        方式然后再进行处理,建议用SAX解析方式,大概的思路就是记录当前开始解析的下表以及解析结束的下标
        然后实现ClickableSpan接口在的ocClick方法和updateDrawState中进行操作,本人是写了一个接口
        回调,吧需要的全部回调过去
        */
        Spanned spanned = Html.fromHtml(mData, null, new MyTagHandler());
        super.setText(spanned, type);
    }




    //实现Html.TagHandler接口
    class MyTagHandler implements Html.TagHandler {
        private int startIndex = 0;
        private int stopIndex = 0;
        private String mId = "";
        private int mType = -1;
        private String mName = "";

        @Override
        //重写handleTag解析
        public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) {

            if (tag.equalsIgnoreCase("user")) {
                //如果是开头
                if (opening) {
                    //记录当前下表
                    startIndex = output.length();
                } else {
                    //结尾开始对数据进行处理
                    endGame(output);
                }
            } else if (tag.equalsIgnoreCase("topic")) {
                if (opening) {
                    startIndex = output.length();
                } else {
                    endGame(output);
                }
            }

        }

        public void endGame(Editable output) {
            //获取到结束位置的下表
            stopIndex = output.length();

            //使用pull解析,获取标签内的属性
            XmlPull(output);
            //根据不同的类型添加不同的前缀
            if (mType == 1) {
                output.insert(startIndex, "@");
            } else if (mType == 2) {
                output.insert(startIndex, "#");
            }
            Log.e("yl", "endGame: " + output.toString());

            //因为多添加了一个符号所以截止位置需要+1
            stopIndex += 1;
            //startIndex+1是因为获取name的时候为了不把前缀的符号包括进去所以下标 前移一位
            output.setSpan(new GameSpan(output.subSequence(startIndex + 1, stopIndex).toString(),
                    mId, mType), startIndex, stopIndex, Spanned.SPAN_MARK_MARK);
            //在结尾处添加空格
            output.insert(stopIndex, " ");
        }

        //集成ClickableSpan 的点击事件,重写onClick方法
        private class GameSpan extends ClickableSpan {
            private String mName;
            private int mType;
            private String mId;

            public GameSpan(String mName, String mId, int mType) {
                this.mName = mName;
                this.mId = mId;
                this.mType = mType;
            }

            @Override
            //重写点击事件
            public void onClick(View v) {
                //设置点击事件
                if (mOnHtmlTextClick != null) {
                    mOnHtmlTextClick.onClick(mName, mId, mType);
                }

            }

            @Override
            //对截取出来的字段设置字体颜色
            public void updateDrawState(TextPaint ds) {


                if (mType == 1) {
                    ds.setColor(getResources().getColor(R.color.colorAccent));
                } else {
                    ds.setColor(getResources().getColor(R.color.colorPrimary));
                }
                //设置文字接口回调
                if (mOnHtmlTextClick != null) {
                    mOnHtmlTextClick.onupdateDrawState(ds, mType);
                }
            }
        }

        //使用XML中的Pull解析,再次希望各位自己重新写一个解析方式 包括实现方法都不要用Html.TagHandler
        private void XmlPull(Editable output) {
            try {
                //字节数组输入流
                ByteArrayInputStream mInputStream;
                if (mData != null && !"".equals(mData)) {
                    //创建字节数组输入流
                    mInputStream = new ByteArrayInputStream(mData.getBytes());
                } else {
                    return;
                }
                //创建xmlPull解析器
                XmlPullParser parser = Xml.newPullParser();
                ///初始化xmlPull解析器,内容,格式
                parser.setInput(mInputStream, "utf-8");
                //读取文件的类型
                int type = parser.getEventType();
                //无限判断文件类型进行读取
                while (type != XmlPullParser.END_DOCUMENT) {
                    switch (type) {
                        //开始标签
                        case XmlPullParser.START_TAG:
                            //当内容里面包含其中一个标签的时候进行解析处理
                            if ("user".equals(parser.getName()) || "topic".equals(parser.getName())) {
                                //必须要先获取属性 如果先获取值 则无法获取到属性
                                //获取id属性
                                String id = parser.getAttributeValue(null, "id");
                                //获取type属性
                                String strType = parser.getAttributeValue(null, "type");

                                //获取user或topic的值
                                mName = parser.nextText();
                                //如果当前解析的值是当前截取的字段,获取当前解析的属性
                                if (mName.equals(output.subSequence(startIndex, stopIndex).toString())) {
                                    //属性赋值用于点击事件判断
                                    mId = id;
                                    try {
                                        mType = Integer.valueOf(strType);
                                    } catch (Exception e) {
                                        mType = 0;
                                    }
                                    type = XmlPullParser.END_DOCUMENT;
                                }
                            }
                            break;
                        //结束标签
                        case XmlPullParser.END_TAG:
                            //                            Log.e("yl", "XmlPull: 结束标签解析");
                            break;
                    }
                    //继续往下读取标签类型
                    type = parser.next();
                }
            } catch (Exception e) {
            }
        }
    }

    //接口回调
    public interface OnHtmlTextClick {
        //点击事件回调
        void onClick(String name, String id, int type);
        //文字颜色回调 包括前缀符号
        void onupdateDrawState(TextPaint ds, int type);
    }
}

在item的布局中需要给layout设置
android:descendantFocusability=”afterDescendants”

Demo下载地址

你可能感兴趣的:(随手记)