自定义圆头柱状图

自己的项目碰到需要自定义圆头柱状图,记录下来


public abstract class BaseCoordinateView extends View {
    public static final String TAG = "MChartView";

    private RectF mRealRect0;
    private RectF mRealRect1;
    private RectF mRealRect2;

    private Paint mXAxisPaint;
    private Paint mYAxisPaint;

    private PointF mOriginPoint;

    private boolean mNeedXAxis = true, mNeedYAxis = true;

    public BaseCoordinateView(Context context, AttributeSet attrs) {
        super(context, attrs);

        init0(attrs);
    }

    public BaseCoordinateView(Context context) {
        super(context);

        init0(null);
    }

    private void init0(AttributeSet attrs) {
        float _1dp = ViewUtils.dp2px(getContext(), 1);

        float xStroke = _1dp * 1.0f;
        mXAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mXAxisPaint.setStrokeWidth(xStroke);
        mXAxisPaint.setColor(Color.parseColor("#9b9b9b"));
        mXAxisPaint.setStyle(Paint.Style.FILL);

        float yStroke = _1dp * 1.0f;
        mYAxisPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mYAxisPaint.setStrokeWidth(yStroke);
        mYAxisPaint.setColor(Color.LTGRAY);
        mYAxisPaint.setStyle(Paint.Style.FILL);

        mOriginPoint = new PointF();
    }

    public void reDraw() {
        mRealRect0 = null;
        invalidate();
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);

        if (getWidth() + getHeight() <= 0) return;

        if (mRealRect0 == null) {
            initRealRect();
        }

        if (mNeedXAxis) {
            drawXAxis(canvas);
        }

        if (mNeedYAxis) {
            drawYAxis(canvas);
        }

        mRealRect1.set(mRealRect0); // avoid alloc, different rectangle
        mRealRect2.set(mRealRect0);
        beforeDraw(canvas, mRealRect1);

        drawChart(canvas, mRealRect2);
    }

    private void initRealRect() {
        mRealRect0 = new RectF();
        mRealRect0.left = getPaddingLeft();
        mRealRect0.right = getWidth() - getPaddingRight();
        mRealRect0.top = getPaddingTop();
        mRealRect0.bottom = getHeight() - getPaddingBottom();

        narrowMainRect(mRealRect0);

        mOriginPoint.set(mRealRect0.left, mRealRect0.bottom);

        mRealRect1 = new RectF();
        mRealRect2 = new RectF();
    }

    protected void needXAxis(boolean isNeed) {
        mNeedXAxis = isNeed;
    }

    protected void needYAxis(boolean isNeed) {
        mNeedYAxis = isNeed;
    }

    /**
     * Before the content draws, after draw axis.
     *
     * @param c
     * @param realRect
     */
    protected void beforeDraw(Canvas c, RectF realRect) {
    }

    protected abstract void drawChart(Canvas c, RectF realRect);

    protected void narrowMainRect(RectF rectF) {
        int padding = ViewUtils.dp2px(getContext(), 5);
        ViewUtils.narrowRectF(rectF, padding);
    }

    public Paint getXAxisPaint() {
        return mXAxisPaint;
    }

    public Paint getYAxisPaint() {
        return mYAxisPaint;
    }

    private void drawXAxis(Canvas c) {
        // move down to draw x axis
        float offset = getXAxisOffset();
        c.drawLine(mOriginPoint.x, mOriginPoint.y + offset, mRealRect0.right, mOriginPoint.y + offset, mXAxisPaint);
    }

    protected float getXAxisOffset() {
        return mXAxisPaint.getStrokeWidth() / 2;
    }

    private void drawYAxis(Canvas c) {
        // move left to draw y axis
        float offset = getYAxisOffset();
        c.drawLine(mOriginPoint.x - offset, mOriginPoint.y, mOriginPoint.x - offset, mRealRect0.top, mYAxisPaint);
    }

    protected float getYAxisOffset() {
        return mYAxisPaint.getStrokeWidth() / 2;
    }
}

public abstract class AbsPartsChartView extends BaseCoordinateView {
    /**
     * exactly same as list.size
     * initialized in #setDatas()
     */
    protected int COUNT = -1;
    protected float MAX = 100;

    private float mPaddingLeft = 0.0f, mPaddingRight = 0.0f;

    private List<Item> mItemList;
    private List<PointF> mPointList;

    private boolean mPointInited = false; //

    protected int mNormalColor = 0xFFf1e9e9, mHighLightColor = 0xFFffc107;

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

    public AbsPartsChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    /**
     * draw the paddings of item INSIDE the coordinate
     *
     * @param l left
     * @param t top
     * @param r right
     * @param b bottom
     */
    public void setInnerPadding(float l, float t, float r, float b) {
        mPaddingLeft = l;
        mPaddingRight = r;
    }

    public void setColors(int normal, int highLight) {
        mNormalColor = normal;
        mHighLightColor = highLight;
    }

    @Override
    protected void drawChart(Canvas c, RectF realRect) {
        if (!mPointInited) {
            makePoints(realRect);
        }

        for (int i = 0; i < COUNT; i++) {
            PointF p = mPointList.get(i);
            Item item = mItemList.get(i);

            drawItem(c, item, p, realRect);
        }
    }

    private void makePoints(RectF rect) {
        float width = rect.right - rect.left - mPaddingLeft - mPaddingRight;
        float height = rect.bottom - rect.top;

        float partWidth = width / (COUNT - 1);
        float startX = rect.left + mPaddingLeft;
        float startY = rect.bottom;// should bottom rect.top -> rect.bottom
        for (int i = 0; i < COUNT; i++) {
            Item item = mItemList.get(i);
            float progress = item.progress;

            float x = startX + i * partWidth;
            float y;
            if(progress > 0){
                y = startY - progress / MAX * height;
                if(y < 0){
                    y = rect.top;
                }
            }else {
                y = -1;
            }

            PointF p = mPointList.get(i);
            p.set(x, y);
        }

        mPointInited = true;
    }

    protected abstract int drawItem(Canvas c, Item item, PointF itemPoint, RectF realRect);

    public void setDatas(List<Item> list) {
        setDatas(list, true);
    }

    public void setDatas(List<Item> list, boolean needInvalidate) {
        mItemList = list;

        COUNT = mItemList.size();
        mPointList = new ArrayList<PointF>(COUNT);
        for (int i = 0; i < COUNT; i++) {
            PointF p = new PointF();
            mPointList.add(p);
        }

        mPointInited = false;

        if (needInvalidate) {
            invalidate();
        }
    }

    public void setMax(float max) {
        MAX = max;
    }

    public class Item {
        public float progress;
        public boolean highLight = false;
    }
}

public class HistogramChartView extends AbsPartsChartView {
    private float mRectWidth;
    private Paint mRectPaint;

    private Paint mPointPaint;

    public HistogramChartView(Context context) {
        super(context);

        init();
    }

    public HistogramChartView(Context context, AttributeSet attrs) {
        super(context, attrs);
        init();
    }

    protected void init() {
        mPointPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mPointPaint.setStyle(Paint.Style.FILL);
        mPointPaint.setStrokeWidth(5);
        mPointPaint.setColor(Color.RED);

        mRectWidth = ViewUtils.dp2px(getContext(), 10);

        mRectPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
        mRectPaint.setStyle(Paint.Style.FILL);
        mRectPaint.setColor(mNormalColor);
    }

    @Override
    protected int drawItem(Canvas c, Item item, PointF itemPoint, RectF realRect) {
        if (itemPoint.y > 0) {
            mRectPaint.setColor(item.highLight ? mHighLightColor : mNormalColor);
            RectF rect = makeHistogramRect(itemPoint, realRect.bottom, mRectWidth);
//            c.drawRect(rect, mRectPaint);

            // TODO: 2016/7/1 17:04modify ---
            RoundRectShape rr = new RoundRectShape(new float[]{8, 8, 8, 8, 0, 0, 0, 0}, null, null);
            ShapeDrawable shapeDrawable = new ShapeDrawable(rr);
            shapeDrawable.getPaint().setColor(mRectPaint.getColor());
            Rect r = new Rect();
            rect.round(r);
            shapeDrawable.setBounds(r);
            shapeDrawable.draw(c);
            //---
        }

        return 0;
    }

    private RectF makeHistogramRect(PointF p, float bottom, float width) {
        RectF rect = new RectF();
        rect.left = p.x - width / 2;
        rect.right = p.x + width / 2;
        rect.top = p.y;
        rect.bottom = bottom;
        return rect;
    }


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值