Android自定义view可拖动的柱状图折线图组合可拖动的折线图

公司最近一个需求就是需要每年的每个月的消费概况的统计图 ,因为涉及到一些乱七八糟的需求 。先看图

其中要求本年未到的年份不一样的颜色,且数据不用画出来当然也没有数据。折线下面有个阴影。所以决定自己撸个图。看布局:

<com.py.ysl.view.myview.BarGraphView
        android:id="@+id/bar_view"
        android:layout_width="match_parent"
        android:layout_height="250dp"
        custom:bargrapColor="#22ffffff"
        custom:textSize="14sp"
        android:visibility="gone"
        custom:textColor="#79ABFF"
        />

再看attr这个就不用解释了吧,不知道请到宏洋大神的博客里搜zidingyiview

<declare-styleable name="MyChartView">
        <attr name="bargrapColor" format="color"/>
        <attr name="selectRightColor" format="color"/>
        <attr name="xyColor" format="color"/>
        <attr name="textSize" format="dimension"/>
        <attr name="textColor" format="color"/>
    </declare-styleable>

然后看三部曲了,onMeasure,onLayout,onDraw

第一步当然是测量长宽了

 @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width;
        int height;
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = widthSize * 1 / 2;
        }
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = heightSize * 1 / 2;
        }

        setMeasuredDimension(width, height);
    }

然后onlayout

 @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (ischangeFirst) {
            ischangeFirst =false;
            mHeight = getHeight();
            mSize = getWidth() /valueSize * 2;
            mChartWidth = getWidth() / valueSize * 2;
            textStartplace = getWidth() / valueSize * 2;
            textWidth = getWidth() / valueSize * 2;
            linearStartX = mSize / 2;
            xOri = 0;
            yOri = getHeight()/3*2;
            minXInit = getWidth() - mSize * (valueSize - 1) - mSize / 2;//计算最小的长度
            minZxInit = getWidth() - mSize * (valueSize);
            maxXInit = linearStartX;
            zhuStartX = 0;
            maxZxInit = mSize;
            initData();
        }
        super.onLayout(changed, left, top, right, bottom);
    }

最后ondraw

@Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        mPaint.setColor(xyColor);
        //渐变
        gradient = new LinearGradient(0,0,getWidth(),mHeight/3*2,context.getResources().getColor(R.color.color_7c98ff),context.getResources().getColor(R.color.color_77b0ff),Shader.TileMode.REPEAT);
        mbackgroundPaint.setShader(gradient);
        canvas.drawRect(0, 0, getMeasuredWidth(), mHeight/3*2, mbackgroundPaint);
        //画柱状图
        drawRect(canvas);
        //划地下月份
       drawMonth(canvas);
       //画折线图和圆点
        drawLine(canvas);
        Log.e("234","linearStartX===="+linearStartX);
    }

标注已经写的很清楚了,还不知道的欢迎评论。

最后加上全部的代码

package com.py.ysl.view.myview;

import android.animation.Animator;
import android.animation.ValueAnimator;
import android.content.Context;
import android.content.res.TypedArray;
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.RectF;
import android.graphics.Shader;
import android.util.AttributeSet;
import android.util.Log;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
import android.view.animation.DecelerateInterpolator;

import com.py.ysl.R;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author lizhijun 2018.8.1
 * 自定义柱状图
 */
public class BarGraphView extends View{

    private int bargrapColor;//柱状图的颜色
    private int selectRightColor;
    private int xyColor;//
    private int textSize;//月份字体大小
    private int textColor;//月份字体颜色
    private Paint mPaint, mChartPaint,mbackgroundPaint;//横轴画笔、柱状图画笔、背景图画笔
    private Paint lineapaint;//折线的画笔
    private Paint dotPain;//圆点的画笔
    private Paint zxbPaint;//折线下面的背景色
    private Rect mBound;
    private float mHeight, mChartWidth, mSize;//屏幕宽度高度、柱状图起始位置、柱状图宽度
    private float textStartplace,textWidth;//月份起始位置、月份的间隔宽度
    //x轴的原点坐标
    private int xOri;
    //y轴的原点坐标
    private int yOri;
    //第一个点对应的最大Y坐标
    private float maxXInit;
    //第一个点对应的最小X坐标
    private float minXInit;

    //第一个柱形的最大Y坐标
    private float maxZxInit;
    //第一个柱形对应的最小X坐标
    private float minZxInit;
    private  LinearGradient gradient;//背景渐变色

    private float linearStartX;//折线第一个点
    private float zhuStartX;//柱形第一个位置
    private Context context;
    //是否在ACTION_UP时,根据速度进行自滑动,没有要求,建议关闭,过于占用GPU
    private boolean isScroll = false;
    //是否正在滑动
    private boolean isScrolling = false;
    //点击的点对应的X轴的第几个点,默认1
    private int selectIndex = 1;
    //数据源
    //x轴坐标对应的数据
    private List<String> xValue = new ArrayList<>();
    //y轴坐标对应的数据
    private int yValue =0;
    //折线对应的数据
    private Map<String, Integer> value = new HashMap<>();

    private int posMonth = 12;//当前月份,今年若超过当前月份的则不画
    private int posPlace = 0;//一开始的位移 用于显示到最新的月份


    private boolean isMonthFirst = false;//用于位移时是否第一次改变数据
    private boolean isRectFirst = false;
    private boolean ischangeFirst = true;//防止onlayout两次改变数据
    private int valueSize = 12;//正常分割为12份

    //速度检测器
    private VelocityTracker velocityTracker;

    public BarGraphView(Context context){
        this(context,null);

    }
    public BarGraphView(Context context,AttributeSet attrs){
        this(context,attrs,0);
    }
    public BarGraphView(Context context,AttributeSet attrs,int defStyleAttr){
        super(context,attrs,defStyleAttr);
        this.context = context;
        initView(context,attrs,defStyleAttr);
    }

    private void initView(Context context,AttributeSet attrs,int defStyleAttr){
        TypedArray array =context.getTheme().obtainStyledAttributes(attrs, R.styleable.MyChartView,defStyleAttr,0);
        int count = array.getIndexCount();
        for (int i=0;i<count;i++){
            int attr = array.getIndex(i);
            switch (attr){
                case R.styleable.MyChartView_bargrapColor:
                    bargrapColor = array.getColor(attr, Color.YELLOW);
                    break;
                case R.styleable.MyChartView_selectRightColor:
                    selectRightColor = array.getColor(attr, Color.YELLOW);
                    break;
                case R.styleable.MyChartView_xyColor:
                    xyColor = array.getColor(attr, Color.YELLOW);
                    break;
                case R.styleable.MyChartView_textSize:
                    textSize =array.getDimensionPixelSize(attr, (int) TypedValue.applyDimension(
                            TypedValue.COMPLEX_UNIT_SP, 12, getResources().getDisplayMetrics()));
                    break;
                case R.styleable.MyChartView_textColor:
                    textColor = array.getColor(attr, Color.YELLOW);
                    break;

            }
        }
        array.recycle();
        init();
    }


    /**
     * 初始化画笔
     */
    private void init(){
        //地下字体的画笔
        mPaint = new Paint();
        mPaint.setAntiAlias(true);

        //柱状体的画笔
        mBound = new Rect();
        mChartPaint = new Paint();
        mChartPaint.setAntiAlias(true);
        mChartPaint.setColor(bargrapColor);

//背景的画笔
        mbackgroundPaint = new Paint();
        mbackgroundPaint.setAntiAlias(true);
//        mbackgroundPaint.setColor(Color.parseColor("#79ABFF"));

//折线的画笔
        lineapaint =  new Paint();
        lineapaint.setAntiAlias(true);

//圆点的画笔
        dotPain =  new Paint();
        dotPain.setAntiAlias(true);
//折线下面的背景色
        zxbPaint = new Paint();
        zxbPaint.setAntiAlias(true);

    }

    /**
     * 数据初始化
     */
    private void initData(){


    }
    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width;
        int height;
        int widthSize = MeasureSpec.getSize(widthMeasureSpec);
        int heightSize = MeasureSpec.getSize(heightMeasureSpec);
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        if (widthMode == MeasureSpec.EXACTLY) {
            width = widthSize;
        } else {
            width = widthSize * 1 / 2;
        }
        if (heightMode == MeasureSpec.EXACTLY) {
            height = heightSize;
        } else {
            height = heightSize * 1 / 2;
        }

        setMeasuredDimension(width, height);
    }
    //计算高度宽度
    @Override
    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
        if (ischangeFirst) {
            ischangeFirst =false;
            mHeight = getHeight();
            mSize = getWidth() /valueSize * 2;
            mChartWidth = getWidth() / valueSize * 2;
            textStartplace = getWidth() / valueSize * 2;
            textWidth = getWidth() / valueSize * 2;
            linearStartX = mSize / 2;
            xOri = 0;
            yOri = getHeight()/3*2;
            minXInit = getWidth() - mSize * (valueSize - 1) - mSize / 2;//计算最小的长度
            minZxInit = getWidth() - mSize * (valueSize);
            maxXInit = linearStartX;
            zhuStartX = 0;
            maxZxInit = mSize;
            initData();
        }
        super.onLayout(changed, left, top, right, bottom);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
//        mPaint.setColor(xyColor);
        //渐变
        gradient = new LinearGradient(0,0,getWidth(),mHeight/3*2,context.getResources().getColor(R.color.color_7c98ff),context.getResources().getColor(R.color.color_77b0ff),Shader.TileMode.REPEAT);
        mbackgroundPaint.setShader(gradient);
        canvas.drawRect(0, 0, getMeasuredWidth(), mHeight/3*2, mbackgroundPaint);
        //画柱状图
        drawRect(canvas);
        //划地下月份
       drawMonth(canvas);
       //画折线图和圆点
        drawLine(canvas);
        Log.e("234","linearStartX===="+linearStartX);
    }

    //划柱形Rect
    private void drawRect(Canvas canvas){
        if (value==null||xValue==null||value.size()==0||xValue.size()==0)
            return;
        int sizeCount = value.size();
        //新建图层
        if (isRectFirst) {
            isRectFirst = false;
            zhuStartX = zhuStartX - mSize * posPlace;
        }
        int layerId = canvas.saveLayer(0, 0, getWidth(), getHeight(), null, Canvas.ALL_SAVE_FLAG);
        for (int i = 0; i < sizeCount; i++) {
            mChartPaint.setStyle(Paint.Style.FILL);
            //画柱状图
            float rectX = zhuStartX+  (mSize) * (i);
            RectF rectF = new RectF();
            rectF.left = rectX;
            rectF.right = rectX + mSize;
            rectF.bottom = mHeight/3*2;
            rectF.top = (mHeight/5);
            if (i%2!=0) {
                canvas.drawRect(rectF, mbackgroundPaint);
            }else {
                canvas.drawRect(rectF, mChartPaint);
            }
        }
        //保存图层
        canvas.restoreToCount(layerId);
    }
    //划地下月份
    private void drawMonth(Canvas canvas){
        if (value==null||xValue==null||value.size()==0||xValue.size()==0)
            return;
        mPaint.setTextSize(textSize);
        mPaint.setTextAlign(Paint.Align.CENTER);
        int sizeCount = value.size();
        if (isMonthFirst) {
            isMonthFirst = false;
            linearStartX = linearStartX - mSize * posPlace;
        }
        for (int i=0;i<sizeCount;i++){
            float   tx = linearStartX + (mSize) * i;
            String text =String.valueOf(i + 1)+"月";
            mPaint.getTextBounds(text,0,text.length(),mBound);
            if (i+1 <= posMonth){
                mPaint.setColor(textColor);//要写在draw里面不然画不出来
                canvas.drawText(text,tx , mHeight/3*2+ mBound.height()+10,mPaint);
            }else {
                mPaint.setColor(context.getResources().getColor(R.color.color_498DFF));//要写在draw里面不然画不出来
                canvas.drawText(text,tx , mHeight/3*2+ mBound.height()+10,mPaint);
            }

            textStartplace+= textWidth;
        }
    }

    /**
     * 画折线图和圆点
     * @param canvas
     */
    private void drawLine(Canvas canvas){
        if (value==null||xValue==null||value.size()==0||xValue.size()==0)
            return;
        int sizeCount = value.size();
        lineapaint.setColor(Color.parseColor("#ffffff"));
        lineapaint.setStrokeWidth(dpToPx(1));
        lineapaint.setAntiAlias(true);
        lineapaint.setStyle(Paint.Style.STROKE);
        dotPain.setColor(Color.parseColor("#ffffff"));
        dotPain.setAntiAlias(true);
        //划折线
        Path path = new Path();
        Path bcpath = new Path();
        float x = linearStartX + (mSize) * 0;
        float y = yOri - yOri * value.get(xValue.get(0)) / yValue;
        path.moveTo(x,y);
        bcpath.moveTo(x,mHeight/3*2);
        bcpath.lineTo(x,y);
        LinearGradient bgGradient = new LinearGradient(0,y,0,mHeight/3*2,
                context.getResources().getColor(R.color.color_4E7FE0),
                context.getResources().getColor(R.color.color_7C98FF),Shader.TileMode.CLAMP);
        int count=0;//记录第几月份好用于计算出x的值
        boolean isSub = false;
        for (int i=1;i<sizeCount;i++){
            y = yOri - yOri  * value.get(xValue.get(i)) / yValue;
            x = linearStartX + (mSize) * i;
            if (i+1<=posMonth) {
                path.lineTo(x, y);
                bcpath.lineTo(x, y);
                count = i;
                isSub= true;
            }else
                break;
        }
        if (isSub){
                x = linearStartX + (mSize) * count;
                bcpath.lineTo(x, mHeight / 3 * 2);
        }else {
            bcpath.lineTo(x,mHeight/3*2);
        }
        bcpath.close();
        canvas.drawPath(path, lineapaint);
          if (count!=0) {//只有一个点则不需要画折线阴影背景
               zxbPaint.setShader(bgGradient);
               zxbPaint.setStrokeWidth(dpToPx(3));
               canvas.drawPath(bcpath,zxbPaint);
          }
        //划圆点
        for (int i=0;i<sizeCount;i++){
            float  ry = yOri - yOri  * value.get(xValue.get(i)) / yValue;
            float   rx = linearStartX + (mSize) * i;
            if (i+1<=posMonth) {
                if (posMonth==0 && value.get(xValue.get(i))<=0)
                    break;
                canvas.drawCircle(rx, ry, dpToPx(3), dotPain);
                if (i == selectIndex - 1) {
                    canvas.drawCircle(rx, ry, dpToPx(4), dotPain);
                    canvas.drawCircle(rx, ry, dpToPx(10), mChartPaint);
                    String text = value.get(xValue.get(i)) + "";
                    drawFloatTextBox(canvas, rx, ry - dpToPx(7), text, i);
                }
            }
        }
    }
    /**
     * 注意:
     * 当屏幕焦点变化时重新侧向起始位置,必须重写次方法,否则当焦点变化时柱状图会跑到屏幕外面
     */

    @Override
    protected void onWindowVisibilityChanged(int visibility) {
        super.onWindowVisibilityChanged(visibility);
        if (visibility == VISIBLE) {
//            mHeight = getHeight();
//            mSize = getWidth() / value.size()*2;
//            mChartWidth = getWidth() / value.size()*2 ;
//            textStartplace = getWidth() / value.size()*2;
//            textWidth= getWidth() / value.size()*2 ;
//            linearStartX = mSize/2;
//            xOri = 0;
//            yOri = getHeight();
//            minXInit = getWidth() - (getWidth() - xOri) * 0.1f - mSize * (xValue.size() - 1);//减去0.1f是因为最后一个X周刻度距离右边的长度为X轴可见长度的10%
//            minZxInit = 0;
        minZxInit = 0;
//            maxXInit = linearStartX;
//            zhuStartX = 0;
//            maxZxInit =mSize;
        }
    }
    private float lastX;
    @Override
    public boolean onTouchEvent(MotionEvent event) {
        if (isScrolling)
            return super.onTouchEvent(event);
        this.getParent().requestDisallowInterceptTouchEvent(true);//当该view获得点击事件,就请求父控件不拦截事件
        obtainVelocityTracker(event);
        switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                lastX = event.getX();
                break;
            case MotionEvent.ACTION_MOVE:
                float offX = event.getX() - lastX;
                lastX = event.getX();
                if (linearStartX + offX < minXInit) {
                    linearStartX = minXInit;
                    zhuStartX = minZxInit;
                } else if (linearStartX + offX > maxXInit) {
                    linearStartX = maxXInit;
                    zhuStartX = 0;
                } else {
                    linearStartX = linearStartX + offX;
                    zhuStartX += offX;
                }
               invalidate();
                break;
            case MotionEvent.ACTION_UP:
                this.getParent().requestDisallowInterceptTouchEvent(false);//当该view获得点击事件,就请求父控件不拦截事件
                clickAction(event);
                scrollAfterActionUp();
                recycleVelocityTracker();
                break;

        }
        return true;
    }
    /**
     * 绘制显示Y值的浮动框
     *
     * @param canvas
     * @param x
     * @param y
     * @param text
     * @param pos 第几个
     */
    private void drawFloatTextBox(Canvas canvas, float x, float y, String text,int pos) {
        int dp6 = dpToPx(6);
        int dp7 = dpToPx(7);
        int dp35 = dpToPx(35);
        int dp40 = dpToPx(40);
        //p1
        Path path = new Path();
        lineapaint.setColor(Color.parseColor("#ffffff"));
        lineapaint.setStrokeWidth(dpToPx(1));
        lineapaint.setAntiAlias(true);
        lineapaint.setStyle(Paint.Style.FILL);
        float left = x-dp40;
        float top = y-dp35;
        float right =x+dp40;
        float bottom =y-dp6;
        if (pos==0){
            left=x-mSize/3;
            right=dp40*2+x-mSize/3;
        }
        if (pos==value.size()-1){
            left=x+mSize/3-dp40*2;
            right=x+mSize/3;
        }
        RectF oval3 = new RectF(left, top, right,bottom);// 设置个新的长方形
        canvas.drawRoundRect(oval3, dpToPx(7), dpToPx(7), lineapaint);//第二个参数是x半径,第三个参数是y半径
        path.moveTo(x,y);
        path.lineTo(x-dp7,y-dp7);
        path.lineTo(x+dp7,y-dp7);
        path.close();
        canvas.drawPath(path, lineapaint);



        mPaint.setTextSize(textSize);
        mPaint.setTextAlign(Paint.Align.CENTER);
        mPaint.setColor(textColor);//要写在draw里面不然画不出来
        mPaint.getTextBounds(text,0,text.length(),mBound);
        if (pos==value.size()-1){
            canvas.drawText(text, x-mSize/3, y  - mBound.height()/3*2-dp7, mPaint);
        }else if (pos==0){
            canvas.drawText(text, x+mSize/3, y  - mBound.height()/3*2-dp7, mPaint);
        }else {
            canvas.drawText(text, x , y  - mBound.height()/3*2-dp7, mPaint);
        }
    }
    /**
     * 获取丈量文本的矩形
     *
     * @param text
     * @param paint
     * @return
     */
    private Rect getTextBounds(String text, Paint paint) {
        Rect rect = new Rect();
        paint.getTextBounds(text, 0, text.length(), rect);
        return rect;
    }
    /**
     * 点击X轴坐标或者折线节点
     *
     * @param event
     */
    private void clickAction(MotionEvent event) {
        if (value==null||xValue==null||value.size()==0||xValue.size()==0)
            return;
        int dp8 = dpToPx(18);
        float eventX = event.getX();
        float eventY = event.getY();
        for (int i = 0; i < xValue.size(); i++) {
            //节点
            float x = linearStartX + mSize * i;
            float y = yOri - yOri * value.get(xValue.get(i)) / yValue;
            if (eventX >= x - dp8 && eventX <= x + dp8 &&
                    eventY >= y - dp8 && eventY <= y + dp8 && selectIndex != i + 1) {//每个节点周围8dp都是可点击区域
                if (i+1<=posMonth) {
                    selectIndex = i + 1;
                    invalidate();
                }
                return;
            }
        }
    }
    /**
     * dp转化成为px
     *
     * @param dp
     * @return
     */
    private int dpToPx(int dp) {
        float density = getContext().getResources().getDisplayMetrics().density;
        return (int) (dp * density + 0.5f * (dp >= 0 ? 1 : -1));
    }
    /**
     * 获取速度跟踪器
     *
     * @param event
     */
    private void obtainVelocityTracker(MotionEvent event) {
        if (!isScroll)
            return;
        if (velocityTracker == null) {
            velocityTracker = VelocityTracker.obtain();
        }
        velocityTracker.addMovement(event);
    }
    /**
     * 回收速度跟踪器
     */
    private void recycleVelocityTracker() {
        if (velocityTracker != null) {
            velocityTracker.recycle();
            velocityTracker = null;
        }
    }
    /**
     * 获取速度
     *
     * @return
     */
    private float getVelocity() {
        if (velocityTracker != null) {
            velocityTracker.computeCurrentVelocity(1000);
            return velocityTracker.getXVelocity();
        }
        return 0;
    }
    /**
     * 手指抬起后的滑动处理
     */
    private void scrollAfterActionUp() {
        if (!isScroll)
            return;
        final float velocity = getVelocity();
        float scrollLength = maxXInit - minXInit;
        if (Math.abs(velocity) < 10000)//10000是一个速度临界值,如果速度达到10000,最大可以滑动(maxXInit - minXInit)
            scrollLength = (maxXInit - minXInit) * Math.abs(velocity) / 10000;
        ValueAnimator animator = ValueAnimator.ofFloat(0, scrollLength);
        animator.setDuration((long) (scrollLength / (maxXInit - minXInit) * 1000));//时间最大为1000毫秒,此处使用比例进行换算
        animator.setInterpolator(new DecelerateInterpolator());
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator valueAnimator) {
                float value = (float) valueAnimator.getAnimatedValue();
                if (velocity < 0 && linearStartX > minXInit) {//向左滑动
                    if (linearStartX - value <= minXInit)
                        linearStartX = minXInit;
                    else
                        linearStartX = linearStartX - value;
                } else if (velocity > 0 && linearStartX < maxXInit) {//向右滑动
                    if (linearStartX + value >= maxXInit)
                        linearStartX = maxXInit;
                    else
                        linearStartX = linearStartX + value;
                }
                invalidate();
            }
        });
        animator.addListener(new Animator.AnimatorListener() {
            @Override
            public void onAnimationStart(Animator animator) {
                isScrolling = true;
            }

            @Override
            public void onAnimationEnd(Animator animator) {
                isScrolling = false;
            }

            @Override
            public void onAnimationCancel(Animator animator) {
                isScrolling = false;
            }

            @Override
            public void onAnimationRepeat(Animator animator) {

            }
        });
        animator.start();

    }

    /**
     * 设置初始值
     * @param value
     * @param xValue
     * @param yValue 纵坐标的最大值
     */
    public void setValue(Map<String, Integer> value, List<String> xValue,int yValue) {
        this.value = value;
        this.xValue = xValue;
        this.yValue = yValue;
        invalidate();
    }

    /**
     * 设置当前月份
     * @param posMonth
     */
    public void setCurrentMonth(int posMonth){
        this.posMonth = posMonth;
        selectIndex = posMonth;
        getDisPlace(posMonth);
        invalidate();

    }
    /**
     * 设置一开始位移
     * @param posPlace
     */
    public void setCurrentDisplace(int posPlace){
        this.posPlace = posPlace;
        isRectFirst = true;
        isMonthFirst = true;
    }
    private void getDisPlace(int posMonth){
        if (posMonth<=6){
            setCurrentDisplace(0);
        }else {
            setCurrentDisplace(posMonth-6);
        }

    }
}

最后就是在activity里面调用了

 

 List<String>StrList = new ArrayList<>();
        List<Integer>intList = new ArrayList<>();
        //折线对应的数据
         Map<String, Integer> value = new HashMap<>();
        for (int i = 0; i < 12; i++) {
            StrList.add((i + 1) + "月");
        }
        value.put( "1月", 600);//60--240
        value.put( "2月", 500);//60--240
        value.put( "3月", 800);//60--240
        value.put( "4月", 900);//60--240
        value.put( "5月", 400);//60--240
        value.put( "6月", 900);//60--240
        value.put( "7月", 1100);//60--240
        value.put( "8月", 1300);//60--240
        value.put( "9月", 1800);//60--240
        value.put( "10月", 1400);//60--240
        value.put( "11月", 1600);//60--240
        value.put( "12月", 1000);//60--240 value.put( "1月", 200);//60--240

       
        bar_view.setValue(value,StrList,1800*3/2);
        bar_view.setCurrentMonth(9);//当没有满一年的时候需要用到

就此一个可滑动的就完成了。最后感谢网上的一些大神,看了一些别人的例子才最后画出来的大神连接

https://blog.csdn.net/u014544193/article/details/54313257

  • 1
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值