美文网首页
介绍一种不同流式标签的实现方式

介绍一种不同流式标签的实现方式

作者: 吕志豪 | 来源:发表于2018-03-08 11:27 被阅读0次

    网上大部分的Android 流式标签实现方式

    1. 自定义ViewGroup,如 Android 实现FlowLayout流式布局(类似热门标签)
    2. 使用RecyclerView的LayoutManager,如快速利用RecyclerView的LayoutManager搭建流式布局
      今天我所要使用的方式是自定义TextView的Span,简单轻巧
    • 首先继承ReplacementSpan,绘制自己所需要的tag,下面给出一种我需要的Tag绘制样式,你可以根据自己需求绘制出更加符合你所需的样式.
    import android.graphics.Canvas;
    import android.graphics.Paint;
    import android.graphics.RectF;
    import android.text.style.ClickableSpan;
    import android.text.style.ReplacementSpan;
    import android.text.style.UpdateLayout;
    import android.view.View;
    
    /**
     * @author吕志豪 .
     * @date 17-12-7  上午9:09.
     * Github :https://github.com/lvzhihao100
     * E-Mail:1030753080@qq.com
     * 简书 :http://www.jianshu.com/u/6e525b929aac
     */
    
    public class TagSpan extends ReplacementSpan {
        private int mSize;
        private int mColor;
        private int mRadius;
        private int mSpace;
        private int lenth = 0;
        private CharSequence text;
        private TextClick textClick;
    
        /**
         * @param color  背景颜色
         * @param radius 圆角半径
         */
        public TagSpan(int color, int radius, int space) {
            mColor = color;
            mRadius = radius;
            mSpace = space;
        }
    
        @Override
        public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
            mSize = (int) (paint.measureText(text, start, end) + 2 * mRadius + 2 * mSpace);
            //mSize就是span的宽度,span有多宽,开发者可以在这里随便定义规则
            //我的规则:这里text传入的是SpannableString,start,end对应setSpan方法相关参数
            //可以根据传入起始截至位置获得截取文字的宽度,最后加上左右两个圆角的半径得到span宽度
            this.text=  text.subSequence(start,end);
            return mSize;
        }
        public int getSize(){
            return mSize;
        }
    
        @Override
        public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
            int color = paint.getColor();//保存文字颜色
            paint.setColor(mColor);//设置背景颜色
            paint.setStyle(Paint.Style.STROKE);
            paint.setStrokeWidth(6);
            paint.setAntiAlias(true);// 设置画笔的锯齿效果
            RectF oval = new RectF(x + mSpace, y + paint.ascent(), x + mSize - mSpace, y + paint.descent());
            //设置文字背景矩形,x为span其实左上角相对整个TextView的x值,y为span左上角相对整个View的y值。paint.ascent()获得文字上边缘,paint.descent()获得文字下边缘
            canvas.drawRoundRect(oval, mRadius, mRadius, paint);//绘制圆角矩形,第二个参数是x半径,第三个参数是y半径
            paint.setColor(color);//恢复画笔的文字颜色
            paint.setStrokeWidth(1);
            paint.setStyle(Paint.Style.FILL_AND_STROKE);
            canvas.drawText(text, start, end, x + mRadius + mSpace, y, paint);//绘制文字
            this.lenth = text.length();
        }
    
        public int length() {
            return lenth;
        }
    
        public void onClick(View v) {
            if (textClick != null) {
                textClick.click(text);
            }
        }
    
        public void setTextClick(TextClick textClick) {
            this.textClick = textClick;
        }
    
        public interface TextClick{
            void click(CharSequence text);
        }
    }
    
    • 处理Span点击事件,需要重写MovementMethod,然后使用
    textView.setMovementMethod( ClickMovementMethod.getInstance());
    
    import android.text.Layout;
    import android.text.Selection;
    import android.text.Spannable;
    import android.text.method.BaseMovementMethod;
    import android.text.method.MovementMethod;
    import android.view.MotionEvent;
    import android.widget.TextView;
    
    import com.eqdd.yiqidian.box.span.TagSpan;
    
    /**
     * @author吕志豪 .
     * @date 18-3-2  下午2:05.
     * Github :https://github.com/lvzhihao100
     * E-Mail:1030753080@qq.com
     * 简书 :http://www.jianshu.com/u/6e525b929aac
     */
    
    public class ClickMovementMethod extends BaseMovementMethod {
        @Override
        public boolean onTouchEvent(TextView widget, Spannable buffer,
                                    MotionEvent event) {
            int action = event.getAction();
    
            if (action == MotionEvent.ACTION_UP || action == MotionEvent.ACTION_DOWN) {
                int x = (int) event.getX();
                int y = (int) event.getY();
    
                x -= widget.getTotalPaddingLeft();
                y -= widget.getTotalPaddingTop();
    
                x += widget.getScrollX();
                y += widget.getScrollY();
    
                Layout layout = widget.getLayout();
                int line = layout.getLineForVertical(y);
                TagSpan[] links = buffer.getSpans(0, buffer.length(), TagSpan.class);
    
                if (links.length != 0) {
                    if (action == MotionEvent.ACTION_UP) {
                        if (x < layout.getLineWidth(line)) {
                            for (int i = 0; i < line; i++) {
                                x += layout.getLineWidth(i);
                            }
                            int num = 0;
                            for (TagSpan link : links) {
                                if (x >= num && x < num + link.getSize()) {
                                    link.onClick(widget);
                                    break;
                                }
                                num += link.getSize();
                            }
                        }
                    } else if (action == MotionEvent.ACTION_DOWN) {
                        Selection.setSelection(buffer,
                                buffer.getSpanStart(links[0]),
                                buffer.getSpanEnd(links[0]));
                    }
                    return true;
                } else {
                    Selection.removeSelection(buffer);
                }
            }
    
            return super.onTouchEvent(widget, buffer, event);
        }
    
    
    
        public static MovementMethod getInstance() {
            if (sInstance == null)
                sInstance = new ClickMovementMethod();
    
            return sInstance;
        }
    
        private static ClickMovementMethod sInstance;
    }
    
    
    • 使用的时候
            textView.setText("");
            String[] split = data.split(",");//获取标签数组
            for (String s : split) {
                SpannableString spanString = new SpannableString(s);
                TagSpan tagSpan = new TagSpan(Color.GREEN, 10, 10);
                tagSpan.setTextClick(text -> {//设置点击事件
                    // TODO: 做点击处理
                });
                spanString.setSpan(tagSpan, 0, s.length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
                textView.append(spanString);
            }
            textView.setMovementMethod(new ClickMovementMethod());
    

    相关文章

      网友评论

          本文标题:介绍一种不同流式标签的实现方式

          本文链接:https://www.haomeiwen.com/subject/tdgefftx.html