Android 柱状图 给柱状图添加指示器

QQ视频20170725110114.gif

绘制柱状我就不多说了,自行查看如何绘制

我们来看看下面的指示器 是如何绘制的 首先我们来看看跟之前的onDraw 有什么区别

mIndexMoveMeasure 计算了 指示器于柱状图 移动的差距比例 DrawIndex 绘制指示器

Paste_Image.png
DrawIndex 我们来看看里面做了什么
  • 首先这里绘制了 指示器上的三角形 moveX 计算指示器要移动的距离 通过刚才计算的 比例来计算


    Paste_Image.png
  • 绘制指示器文本框 限制右边距

Paste_Image.png
  • 判断指示器 当前处于的位置 判断 topX 也就是三角形的 上边的x坐标 是不是 矩阵范围内, 不过这个时候有个问题空白区域的时候 就找不到因此 做一个处理 找不到时 绘制上一次绘制的文本
Paste_Image.png
完整代码

<code>

package com.app.framework.widget.chart.rect;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.LinearGradient;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Shader;
import android.support.annotation.Nullable;
import android.text.method.NumberKeyListener;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;

import java.util.ArrayList;
import java.util.List;


public class SlideRectChart extends AbsChart {
    private static final String TAG = "SlideRectChart";

    /**
     * 柱子的画笔
     */
    private Paint mSlideRectPaint;
    /**绘制时间画笔*/
    private  Paint mTimePaint;

    /**指示器画笔*/
    private Paint mIndexPaint;
    /**指示器文本画笔*/
    private Paint mIndexTxtPaint;
    /**
     * 柱子的大小
     */
    private float mRectSize;

    /**move手指移动与 指针移动的比例*/
    private float mIndexMoveMeasure;

    /**
     * 柱子之间的边距
     */
    private float mRectLeft;

    /**
     * 右边超出的范围
     */
    private float mRectDrawWidth;

    public ArrayList<TimeData> mTimeData;

    /**判断单位*/
    private SlideRectEnum tag =SlideRectEnum.hour;

    private List<Rect> mRectList;
    private LinearGradient mLinearGradient;

    public  enum  SlideRectEnum{
        day,
        month,
        year,
        hour,

    }
    public SlideRectChart(Context context) {
        super(context);
        init();
    }

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

    private void init() {
        if (mSlideRectPaint == null) {
            mSlideRectPaint = new Paint();
        }
        mSlideRectPaint.setAntiAlias(true);
        mSlideRectPaint.setStyle(Paint.Style.FILL);
        mSlideRectPaint.setColor(Color.GREEN);
        if(mTimePaint==null){
            mTimePaint=new Paint();
        }
        mTimePaint.setAntiAlias(true);
        mTimePaint.setStyle(Paint.Style.STROKE);
        mTimePaint.setColor(Color.BLACK);
        mTimePaint.setTextSize(dip2px(12));
        mTimePaint.setTextAlign(Paint.Align.LEFT);


        if(mIndexPaint==null){
            mIndexPaint=new Paint();
        }
        mIndexPaint.setAntiAlias(true);
        mIndexPaint.setStyle(Paint.Style.FILL);
        mIndexPaint.setColor(Color.BLUE);

        if(mIndexTxtPaint==null){
            mIndexTxtPaint=new Paint();
        }
        mIndexTxtPaint.setAntiAlias(true);
        mIndexTxtPaint.setStyle(Paint.Style.FILL);
        mIndexTxtPaint.setColor(Color.WHITE);
        mIndexTxtPaint.setTextSize(dip2px(12));
        mIndexTxtPaint.setTextAlign(Paint.Align.CENTER);


        getBrokenLinePaint().setTextSize(dip2px(12));
        getBrokenLinePaint().setStrokeWidth(dip2px(0.5f));
        getBrokenLinePaint().setStyle(Paint.Style.FILL);
    }

    @Override
    public void setValue(float[] value) {
        super.setValue(value);
        this.mSlideX=0;
    }
    public  void  setTimeData(ArrayList<TimeData> timeData){
        this.mTimeData =timeData;
    }
    public  void  setTag(SlideRectEnum slideRectEnum){
        this.tag=slideRectEnum;
    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        mRectSize = getViewWidth() / 24;
        mRectLeft = dip2px(4);
        mRectList=new ArrayList<>();
        mLinearGradient = new LinearGradient(getBrokenLineLeft()-1 ,getBrokenLineTop(),getBrokenLineLeft(),getBrokenLineTop(),new int[]{0x00ffffff,Color.BLUE}, null, Shader.TileMode.CLAMP);
        getBrokenLinePaint().setShader(mLinearGradient);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        onTouchEvent(event);
        return true;
    }

    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        /**计算最多移动的距离*/
        mRectDrawWidth = ((mRectLeft * mPoints.length) + (mRectSize * mPoints.length + getBrokenLineLeft() - getViewWidth()));

        mIndexMoveMeasure=getNeedDrawWidth()/mRectDrawWidth;
        DrawRect(canvas);

        DrawIndex(canvas);
    }
    private String oldText="";
    /**绘制指示器*/
    private void DrawIndex(Canvas canvas) {
        float moveX=mSlideX*mIndexMoveMeasure;
        float leftX=getBrokenLineLeft()+moveX;
        float rightX=getBrokenLineLeft()+mRectSize+moveX;
        float topX =rightX-(rightX-leftX)/2;
        float topY=getNeedDrawHeight()+getBrokenLineTop()+2;
        float bottomY=getNeedDrawHeight()+getBrokenLineTop()+mRectSize/2;

        if(leftX>=getViewWidth()-mRectSize-mRectLeft){
            leftX=getViewWidth()-mRectSize-mRectLeft;
            rightX=getViewWidth()-mRectLeft;
            topX=rightX-(rightX-leftX)/2;
        }

        Path mPath=new Path();
        mPath.moveTo(leftX,bottomY);
        mPath.lineTo(topX,topY);
        mPath.lineTo(rightX,bottomY);
        mPath.lineTo(leftX,bottomY);
        canvas.drawPath(mPath,mIndexPaint);

        /**绘制指示器举证*/
        Rect belowRect=new Rect();
        int  left= (int) (leftX-getBrokenLineLeft());
        int  right = (int) (leftX+getBrokenLineLeft());
        int  top= (int) (topY+getBrokenLineTop()/1.5);
        int  bottom=getViewHeight();
        if(right>=getViewWidth()-mRectLeft){
            left= (int) (getViewWidth()-mRectLeft-getBrokenLineLeft()*2);
            right= (int) (getViewWidth()-mRectLeft);
        }
        belowRect.left=left;
        belowRect.right=right;
        belowRect.top=top;
        belowRect.bottom=bottom;
        canvas.drawRect(belowRect,mIndexPaint);

        int  bx=belowRect.left+(belowRect.right-belowRect.left)/2;


        for (int i = 0; i < mRectList.size(); i++) {
            Rect rect=mRectList.get(i);
            if(rect.left<=topX && rect.right>=topX ){

                if(tag==SlideRectEnum.hour) {
                    oldText=mTimeData.get(i).getHour() + ":00" + " γ: " + floatKeepTwoDecimalPlaces(getValue()[i]);
                    canvas.drawText(oldText, bx, getHeight() - dip2px(2), mIndexTxtPaint);
                }
                if(tag==SlideRectEnum.day) {
                    oldText=mTimeData.get(i).getDay() + "日" + " γ: " + floatKeepTwoDecimalPlaces(getValue()[i]);
                    canvas.drawText(oldText, bx, getHeight() - dip2px(2), mIndexTxtPaint);
                }
                break;
            }
            if(mRectList.size()==i+1){
                canvas.drawText(oldText, bx, getHeight() - dip2px(2), mIndexTxtPaint);
            }
        }




    }


    /**绘制矩阵*/
    private void DrawRect(Canvas canvas) {
        mRectList.clear();
        for (int i = 0; i < mPoints.length; i++) {
            Point point = mPoints[i];
            Rect rect = new Rect();
            int left = (int) ((mRectLeft * i) + (mRectSize * i + getBrokenLineLeft()) - mSlideX);
            int right = ((int) ((mRectLeft * i) + (mRectSize * i + mRectSize + getBrokenLineLeft() - mSlideX)));

            if(tag==SlideRectEnum.hour){
                if(mTimeData!=null){
                    TimeData timeData=mTimeData.get(i);
                    if(i==0 || timeData.getHour()==1){
                        canvas.drawLine(left,getNeedDrawHeight()+getBrokenLineTop(),left,0,getBrokenLinePaint());
                        canvas.drawText(timeData.getDay()+"日",left+2,getBrokenLineTop(),getBrokenLinePaint());
                    }
                }
            }
            if(tag==SlideRectEnum.day){
                if(mTimeData!=null){
                    TimeData timeData=mTimeData.get(i);
                    if(i==0 || timeData.getDay()==1){
                        canvas.drawLine(left,getNeedDrawHeight()+getBrokenLineTop(),left,0,getBrokenLinePaint());
                        canvas.drawText(timeData.getMonth()+"月",left+2,getBrokenLineTop(),getBrokenLinePaint());
                    }
                }
            }


            /**限制柱状绘制范围*/
            if (left < getBrokenLineLeft()) {
                left = (int) getBrokenLineLeft();
            }
            if (right < getBrokenLineLeft()) {
                right = (int) getBrokenLineLeft();
            }
            rect.left = left;
            rect.right = right;
            rect.bottom = (int) (getNeedDrawHeight() + getBrokenLineTop());
            rect.top = point.y;

            mRectList.add(rect);

            canvas.drawRect(rect, mSlideRectPaint);



        }
    }

    private float mSlideX = 0;
    private float mLastDownX;



    @Override
    public boolean onTouchEvent(MotionEvent event) {

        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                mLastDownX = event.getX();
                return  true;
            case MotionEvent.ACTION_UP:
                mSlideX += (mLastDownX - event.getX());
                mLastDownX = event.getX();

                if (mSlideX <= 0) {
                    mSlideX = 0;
                }
                if (mSlideX >= mRectDrawWidth) {
                    mSlideX = mRectDrawWidth;
                }
                postInvalidate();
                return true;

            case MotionEvent.ACTION_MOVE:
                mSlideX += (mLastDownX - event.getX());
                mLastDownX = event.getX();
                if (mSlideX <= 0) {
                    mSlideX = 0;
                }
                if (mSlideX >= mRectDrawWidth) {
                    mSlideX = mRectDrawWidth;
                }
                postInvalidate();
                return true;

        }
        return true;

    }
}

</code >

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,098评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,213评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,960评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,519评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,512评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,533评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,914评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,804评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,563评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,644评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,350评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,933评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,908评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,146评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,847评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,361评论 2 342

推荐阅读更多精彩内容

  • 发现 关注 消息 iOS 第三方库、插件、知名博客总结 作者大灰狼的小绵羊哥哥关注 2017.06.26 09:4...
    肇东周阅读 12,016评论 4 62
  • 遇见你,没有太多的开始 可能就只是一句话,一句简单的问候 什么时候拥抱,什么时候牵手 什么时候看到你如痴如醉的笑 ...
    虓砚阅读 199评论 0 2
  • 本来,我想以轻松诙谐的语言来写这篇文章,可自己的大学生涯是个反面教材,自己的文字又偏深沉,自己对文字的驾驭又欠缺火...
    北岭老松阅读 481评论 6 7
  • 创建mysql超级用户 groupadd mysql useradd -r -g mysql mysql 解压后更...
    蔚文达阅读 306评论 0 0