美文网首页
自定义view-流式布局

自定义view-流式布局

作者: XJ_crazy | 来源:发表于2018-11-02 20:25 被阅读0次

    总是觉得需求才是促进成长的一大动力哈哈

    由于本人之前是做网页开发的,对于标签的流式布局只需要在flex布局内设置几个属性就能完成了。而转了android之后却没有那么好用的属性了,所以一直都想做一个android版的流式布局
    (网上一搜一大堆,但还是想要自己实现一波)

    公司有一个需求:添加一个奖励标签。效果图如下:


    image.png

    实现思路很简单:
    1.在onMearsure中遍历list,计算出控件需要占据的总高度
    2.在onDraw中同理计算出每一个item的左上角位置,调用drawItem方法绘制出item

    下面是源代码

    import android.content.Context;
    import android.graphics.Canvas;
    import android.graphics.Color;
    import android.graphics.Paint;
    import android.graphics.Path;
    import android.os.Build;
    import android.support.annotation.Nullable;
    import android.support.annotation.RequiresApi;
    import android.util.AttributeSet;
    import android.util.Log;
    import android.view.View;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class CustomFlexLayout extends View {
    
        private static final String TAG = "FlexLayout";
    
        private Paint mPaint;
        private Paint textPaint;
        private Path mPath;
    
        private List<String> list = new ArrayList<>();
    
        private int marginV = 16;//绘制的item的纵向margin值
        private int marginH = 10;//绘制的item的横向margin值
        private int paddingV = 20;//绘制的item的纵向padding值
        private int paddingH = 28;//绘制的item的横向padding值
        private int radius = 4;//绘制的item四个角的半径
        private int backColor = Color.parseColor("#f3f9ff");//绘制的item的背景颜色
        private int textColor = Color.parseColor("#007aff");//绘制的item的背景颜色
        private float textSize = 32f;
    
        private int height;//控件高度,在onMeasure中计算得到
        private int width;//控件宽度,在xml中设置
    
        private int nowWidth;
        private int nowHeight;
    
        private int rectHeight; //矩形高度
    
        //暴露给外边设置item数据的方法
        public void setList(List<String> list) {
            this.list = list;
            requestLayout();
        }
    
        public CustomFlexLayout(Context context) {
            this(context, null);
        }
    
        public CustomFlexLayout(Context context, @Nullable AttributeSet attrs) {
            this(context, attrs, 0);
        }
    
        public CustomFlexLayout(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
    
            init();
        }
    
        private void init() {
            mPaint = new Paint();
            mPaint.setColor(backColor);
            //设置抗锯齿
            mPaint.setAntiAlias(true);
            //设置防抖动
            mPaint.setDither(true);
            //设置填充方式
            mPaint.setStyle(Paint.Style.FILL);
    
    
            textPaint = new Paint();
            textPaint.setColor(textColor);
            //设置文本字体大小
            textPaint.setTextSize(textSize);
            //设置抗锯齿
            textPaint.setAntiAlias(true);
            //设置防抖动
            textPaint.setDither(true);
            //设置填充方式
            textPaint.setStyle(Paint.Style.FILL);
    
            mPath = new Path();
    
            rectHeight = marginV * 2 + paddingV * 2 + getFontHeight(textPaint);
            nowHeight = 0;
            nowWidth = 0;
    
        }
    
        private int getTextLength(String text) {
            return (int) textPaint.measureText(text);
        }
    
        private int getRectWidth(String text) {
            return marginH * 2 + paddingH * 2 + getTextLength(text);
        }
    
        private int getFontHeight(Paint paint) {
            Paint.FontMetrics fm = paint.getFontMetrics();
            //文字基准线的下部距离-文字基准线的上部距离 = 文字高度
            return (int) -(fm.bottom + fm.top);
        }
    
        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
    
            nowWidth = 0;
            nowHeight = rectHeight;
            width = getMeasuredWidth();
    
            int length;
            for (int i=0;i<list.size();i++) {
                length = getRectWidth(list.get(i));
                if (nowWidth + length <= width) {
                    nowWidth += length;
                }else {
                    nowWidth = length;
                    nowHeight += rectHeight;
                }
            }
            height = nowHeight;
    
            setMeasuredDimension(width, height);
    
        }
    
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            nowWidth = 0;
            nowHeight = 0;
    
            for (int i=0;i<list.size();i++) {
                int length = getRectWidth(list.get(i));
                Log.i(TAG, "text:" + list.get(i) + " length:" + length);
                //还未满一行
                if (nowWidth + length <= width) {
                    drawitem(list.get(i), nowWidth, nowHeight, getRectWidth(list.get(i)), canvas);
                    nowWidth += length;
                }else /*满一行*/{
                    nowWidth = 0;
                    nowHeight += rectHeight;
                    drawitem(list.get(i), nowWidth, nowHeight, getRectWidth(list.get(i)), canvas);
                    nowWidth += length;
                }
    
            }
        }
    
        /**
         * 传入的参数分别为文本和矩形左上角横纵坐标,矩形宽度(矩形高度上面已经计算好)和一个画布
         */
        @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
        private void drawitem(String text, int startX, int startY, int rectWidth, Canvas canvas) {
            //Log.i(TAG, "text:" + text);
            //绘制矩形背景
            canvas.drawRoundRect(startX + marginH, startY + marginV, startX + rectWidth - marginH, startY + rectHeight - marginV, radius, radius, mPaint);
            //绘制中心文字
            canvas.drawText(text, startX + (rectWidth/2-getTextLength(text)/2),
                    startY + getFontHeight(textPaint)/2 + rectHeight/2, textPaint);
        }
    }
    

    相关文章

      网友评论

          本文标题:自定义view-流式布局

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