StripeStaticsView.java

import android.content.Context;import android.content.res.TypedArray;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.os.Handler;import android.os.Message;import android.support.annotation.Nullable;import android.util.AttributeSet;import android.view.MotionEvent;import android.view.View;import android.view.ViewGroup;import com.careeach.sport.R;import java.util.List;/** * 条形统计图 */public class StripeStaticsView extends View {    private List<Integer> values;    private List<String> titles;    private int height;    private int width;    private Paint stripePaint;    private Paint stripeSelectedPaint; // 选中状态    private Paint titleTextPaint;       //  题目字    private Paint bodyBackGroundPaint;    private Paint titleBackGroundPaint;    private float itemHeight;             // 一个值对于高度    //ATTR    private int itemColor;          // 条形色彩    private float itemWidth;        // 条形宽度    private float itemSpaceWidth;  // 条形间隙    private int itemSelectColor;    private int maxValue;    private float centerX;    private float startX; // 第一条条形起始X座标    private float moveWidth = 0f;    private float touchStarX = 0;    private float titleHeight;          // 题目高度    private float titleTextY;          // 题目Y坐标    private float titleTextSize;        // 题目字体大小    private float titleTextLineSpace;  // 题目行间隙    private int titleTextColor;         // 题目字色彩    private int titleTextSelectColor;         // 题目字色彩    private int bodyBackGroundColor;         // 主背景    private int titleBackGroundColor;         // 题目背景    private boolean isMove = false;    private boolean isUp = false;    private OnStripeStaticsListener onStripeStaticsListener;    private int selectPosition = -1;    private TouchEventCountThread touchEventCountThread;    private final int HANDLER_WHAT_CLICK = 1;    private final int HANDLER_WHAT_SELECT_CHANGE = 2;    private ViewGroup parentViewGroup;    public StripeStaticsView(Context context) {        super(context);    }    public StripeStaticsView(Context context, @Nullable AttributeSet attrs) {        super(context, attrs);        init(context, attrs);    }    public StripeStaticsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {        super(context, attrs, defStyleAttr);        init(context, attrs);    }    public StripeStaticsView(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) {        super(context, attrs, defStyleAttr, defStyleRes);        init(context, attrs);    }    private void init(Context context, AttributeSet attrs) {        TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.StripeStaticsView);        itemColor = typedArray.getColor(R.styleable.StripeStaticsView_itemColor, Color.BLACK);        itemSelectColor = typedArray.getColor(R.styleable.StripeStaticsView_itemSelectColor, Color.WHITE);        itemSpaceWidth = typedArray.getDimension(R.styleable.StripeStaticsView_itemSpaceWidth, Color.BLACK);        itemWidth = typedArray.getDimension(R.styleable.StripeStaticsView_itemWidth, dip2px(20));        maxValue = typedArray.getInt(R.styleable.StripeStaticsView_maxValue, 100);        titleTextSize = typedArray.getDimension(R.styleable.StripeStaticsView_titleTextSize, sp2px(12));        titleTextLineSpace = typedArray.getDimension(R.styleable.StripeStaticsView_titleTextLineSpace, dip2px(10));        titleTextColor = typedArray.getColor(R.styleable.StripeStaticsView_titleTextColor, Color.WHITE);        titleTextSelectColor = typedArray.getColor(R.styleable.StripeStaticsView_titleTextSelectColor, Color.WHITE);        bodyBackGroundColor = typedArray.getColor(R.styleable.StripeStaticsView_contentBGColor, Color.WHITE);        titleBackGroundColor = typedArray.getColor(R.styleable.StripeStaticsView_titleBGColor, Color.WHITE);        typedArray.recycle();        stripePaint = new Paint();        stripePaint.setColor(itemColor);        stripePaint.setAntiAlias(true);        stripePaint.setStyle(Paint.Style.FILL);        stripeSelectedPaint = new Paint();        stripeSelectedPaint.setColor(itemSelectColor);        stripeSelectedPaint.setAntiAlias(true);        stripeSelectedPaint.setStyle(Paint.Style.FILL);        titleTextPaint = new Paint();        titleTextPaint.setColor(titleTextColor);        titleTextPaint.setTextSize(titleTextSize);        titleTextPaint.setAntiAlias(true);        bodyBackGroundPaint = new Paint();        bodyBackGroundPaint.setColor(bodyBackGroundColor);        bodyBackGroundPaint.setStyle(Paint.Style.FILL);        titleBackGroundPaint = new Paint();        titleBackGroundPaint.setColor(titleBackGroundColor);        titleBackGroundPaint.setStyle(Paint.Style.FILL);        touchEventCountThread = new TouchEventCountThread();    }    @Override    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {        super.onMeasure(widthMeasureSpec, heightMeasureSpec);        width = getMeasuredWidth();        height = getMeasuredHeight();    }    @Override    protected void onDraw(Canvas canvas) {        super.onDraw(canvas);        centerX = (width - itemWidth) / 2;        if (values != null && values.size() > 0) {            startX = ((width / 2) + (itemWidth / 2)) - ((itemWidth * values.size()) + ((values.size() - 1) * itemSpaceWidth));        }        titleHeight = titleTextSize + (titleTextLineSpace * 2);        itemHeight = (height - titleHeight) / maxValue;        titleTextY = height - titleTextSize;        // 主背景        canvas.drawRect(0f, 0, width, height - titleHeight, bodyBackGroundPaint);        // 题目背景        canvas.drawRect(0f, height - titleHeight, width, height, titleBackGroundPaint);        if (values != null && values.size() > 0 && titles != null && titles.size() == values.size()) {            for (int i = 0; i < values.size(); i++) {                int value = values.get(i);                float left = startX + (itemWidth + itemSpaceWidth) * i + moveWidth;                float top = height - titleHeight - (itemHeight * value);                float right = left + itemWidth;                float bottom = height - titleHeight;                String title = titles.get(i);                float textWidth = titleTextPaint.measureText(title, 0, title.length());                float textX = left + ((itemWidth - textWidth) / 2);                // 判断是否核心                if (left >= centerX && left <= (width + itemWidth) / 2) {                    canvas.drawRect(left, top, right, bottom, stripeSelectedPaint);                    // 题目                    titleTextPaint.setColor(titleTextSelectColor);                    canvas.drawText(title, textX, titleTextY, titleTextPaint);                    if (i == 0 || selectPosition != i) {                        Message message = handler.obtainMessage();                        message.what = HANDLER_WHAT_SELECT_CHANGE;                        message.arg1 = i;                        message.sendToTarget();                    }                    selectPosition = i;                } else {                    canvas.drawRect(left, top, right, bottom, stripePaint);                    // 题目                    titleTextPaint.setColor(titleTextColor);                    canvas.drawText(title, textX, titleTextY, titleTextPaint);                }            }        }    }    @Override    public boolean onTouchEvent(MotionEvent event) {        switch (event.getAction()) {            case MotionEvent.ACTION_DOWN:                touchStarX = event.getX();                isMove = false;                isUp = false;                postDelayed(touchEventCountThread, 100);                if(parentViewGroup != null){                    parentViewGroup.requestDisallowInterceptTouchEvent(true);                }                break;            case MotionEvent.ACTION_MOVE:                isMove = true;                if (Math.abs(event.getX() - touchStarX) > 1) {                    moveWidth += event.getX() - touchStarX;                    postInvalidate();                    touchStarX = event.getX();                }                break;            case MotionEvent.ACTION_UP:                isUp = true;                if (isMove) {                    aligning();                }                if(parentViewGroup != null){                    parentViewGroup.requestDisallowInterceptTouchEvent(false);                }                break;        }        //return super.onTouchEvent(event);        return true;    }    /**     * 对齐,让靠两头的条形移至正中间     */    private void aligning() {        if(values == null || values.isEmpty()){            return;        }        Float tagX = null;        Float tagXValue = null;        for (int i = 0; i < values.size(); i++) {            float left = startX + (itemWidth + itemSpaceWidth) * i + moveWidth;            float distance = Math.abs(centerX - left);            if (tagX == null || distance < tagX) {                tagX = distance;                tagXValue = centerX - left;            }        }        if (tagX != null) {            moveWidth += tagXValue;        }        isMove = false;        postInvalidate();    }    public void setValue(List<Integer> values) {        this.values = values;        selectPosition = 0;    }    public void setTitle(List<String> titles) {        this.titles = titles;    }    public void refresh() {        postInvalidate();    }    private int dip2px(float dpValue) {        final float scale = getContext().getResources().getDisplayMetrics().density;        return (int) (dpValue * scale + 0.5f);    }    private float sp2px(float spValue) {        final float scale = getContext().getResources().getDisplayMetrics().scaledDensity;        return (spValue * scale + 0.5f);    }    class TouchEventCountThread implements Runnable {        @Override        public void run() {            if (!isMove && isUp && values != null && values.size() > 0 && titles != null && titles.size() == values.size()) {                for (int i = 0; i < values.size(); i++) {                    float left = startX + (itemWidth + itemSpaceWidth) * i + moveWidth;                    float right = left + itemWidth;                    if (touchStarX >= left && right >= touchStarX) {                        selectTo(i);                        if (onStripeStaticsListener != null) {                            Message message = handler.obtainMessage();                            message.what = HANDLER_WHAT_CLICK;                            message.arg1 = i;                            message.sendToTarget();                        }                        break;                    }                }            }        }    }    Handler handler = new Handler() {        @Override        public void handleMessage(Message msg) {            super.handleMessage(msg);            switch (msg.what) {                case HANDLER_WHAT_CLICK:                    if(onStripeStaticsListener != null) {                        onStripeStaticsListener.onItemClick(msg.arg1);                    }                    break;                case HANDLER_WHAT_SELECT_CHANGE:                    if(onStripeStaticsListener != null) {                        onStripeStaticsListener.onSelectChanged(msg.arg1);                    }                    break;            }        }    };    public void selectTo(int position) {        if (selectPosition == position) {            return;        }        if (position > selectPosition) {            moveWidth -= ((itemWidth + itemSpaceWidth) * (position - selectPosition));        } else {            moveWidth += ((itemWidth + itemSpaceWidth) * (selectPosition - position));        }        postInvalidate();    }    public interface OnStripeStaticsListener {        void onItemClick(int position);        void onSelectChanged(int position);    }    public void setOnStripeStaticsListener(OnStripeStaticsListener onClickListener) {        this.onStripeStaticsListener = onClickListener;    }    public void setParentViewGroup(ViewGroup parentViewGroup) {        this.parentViewGroup = parentViewGroup;    }}

attr.xml增加属性

<declare-styleable name="StripeStaticsView">    <attr name="itemWidth" format="dimension" />    <attr name="itemColor" format="color" />    <attr name="itemSelectColor" format="color" />    <attr name="itemSpaceWidth" format="dimension" />    <attr name="maxValue" format="integer" />    <attr name="titleTextSize" format="dimension" />    <attr name="titleTextLineSpace" format="dimension" />    <attr name="titleTextColor" format="color" />    <attr name="titleTextSelectColor" format="color" />    <attr name="contentBGColor" format="color" />    <attr name="titleBGColor" format="color" /></declare-styleable>

应用

<xxx.StripeStaticsView    android:id="@+id/stripeStaticsView"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:layout_marginTop="@dimen/statics_stripe_view_margin_top"    app:contentBGColor="#7dded4"    app:itemColor="#80ffffff"    app:itemSelectColor="@android:color/white"    app:itemSpaceWidth="5dp"    app:itemWidth="30dp"    app:maxValue="100"    app:titleBGColor="@android:color/white"    app:titleTextColor="@color/txt_describe"    app:titleTextLineSpace="8dp"    app:titleTextSelectColor="@color/colorPrimary"    app:titleTextSize="10sp" />
// 设置值void setValue(List<Integer> values)// 设置值对应的题目(注:数量要对应)void setTitle(List<String> titles)// 设置题目和内容后刷新控件void refresh()// 控件增加在高低滑动控件中时,当手在该控件左右滑动时不会触发高低滑动,添强体验,如ListViewvoid setParentViewGroup(ViewGroup parentViewGroup)