接上文:

Android图表控件MPAndroidChart——曲线图LineChart的使用(多条曲线)

其他相关文章:

Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3.0)

Android图表控件MPAndroidChart——曲线图LineChart的使用(多条曲线)

Android图表控件MPAndroidChart——曲线图LineChart(多条曲线)动态添加数据

Android图表控件MPAndroidChart——柱状图BarChart的使用(多条柱状图)

Android图表控件MPAndroidChart——曲线图+柱状图 CombinedChart的使用

Android图表控件MPAndroidChart——源码修改实现曲线图X轴直尺刻度样式

MPAndroidChart在github上的地址:https://github.com/PhilJay/MPAndroidChart

没想到现在更新文章,日期也更新为当前时间了。

一. 目标效果

对比两张图

     

左图为需要实现的效果,右图为当前的效果,对比X Y轴,当前的图表未展示刻度,而且X轴在0的下方。

总结需要实现的功能

  • X Y轴展示刻度
  • X轴位置从原点(0,0)开始

二. 实现效果

因未找到相关方法设置显示类似直尺样式的刻度(若有相关方法可实现,请告诉我一下),所以只有修改下源码

修改源码之前首先自己在View中画出刻度,然后找到MPAndroidChart库X轴的绘制代码,将自己写的方法添加进去。

注:本文会将长短刻度线都绘制出来,不想要短刻度线,去掉绘制方法即可。绘制效果如下:

2.1 绘制刻度线

2.1.1 绘制方式

绘制刻度线有很多方式,在此简单说一下本文中使用的方式。

先画一条长竖线(长刻度线),然后平移画布一段距离(即刻度线间的间距),在画短刻度线(坐标轴未变,只是画布位置变了,至使表面上看起来线位置变了)

2.1.2 画线

手机坐标轴:

画刻度线:

新建MyScaleView 重写 onDraw()方法

public class MyScaleView extends View {private Paint scalePaint;
    public MyScaleView(Context context) {this(context, null);
    }public MyScaleView(Context context, @Nullable AttributeSet attrs) {this(context, attrs, 0);
    }public MyScaleView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {super(context, attrs, defStyleAttr);
        initPaint();
    }private void initPaint() {scalePaint = new Paint();
        scalePaint.setAntiAlias(true);
        scalePaint.setColor(Color.RED);
        scalePaint.setStrokeWidth(2);
        scalePaint.setStyle(Paint.Style.FILL);
        scalePaint.setDither(true);
    }@Override
    protected void onDraw(Canvas canvas) {super.onDraw(canvas);
        drawScale(canvas);
    }private void drawScale(Canvas canvas) {int scaleGroup = 5;     // 默认1个长刻度间隔4个短刻度,加起来一组5
        int mScaleCount = 101;  //刻度的总个数
        canvas.save();
        int startX = 30;
        int startY = 500;   //即在坐标轴(30,500)处开始画刻度线
        for (int i = 0; i < mScaleCount; i++) {canvas.save();  //记录画布状态
            canvas.translate(10 * i, 0);    //画布平移,即刻度线的间距
            if (i == 0 || i % scaleGroup == 0) {canvas.drawLine(startX, startY, startX, startY - 20, scalePaint);//画长刻度线
            } else {canvas.drawLine(startX, startY, startX, startY - 10, scalePaint);//画短刻度线
            }canvas.restore();//取出保存的状态
        }canvas.restore();
    }
}

最后应用MyScaleView 效果如下

2.2 修改源码

步骤2.1.2中已经在实现了刻度线的绘制,现在只需要将绘制代码,加入MPAndroidChart中即可实现效果

2.2.1 下载源码

下载源码:https://github.com/PhilJay/MPAndroidChart/releases

点击 Downloads Source code(zip) 我下载的版本为v3.0.3  解压后里面的MPChartLib即为MPAndroidChart库源码

2.2.2 寻找X Y轴的绘制类

说下我的思路

首先找到 X轴  XAxis   并没有什么相关绘制代码

接着找到父类  AxisBase  发现 X Y 轴都继承于该类,那肯定和这类相关了

然后发现 AxisBase 类下定义了 相关属性 和 绘制图形相关

沿着 mGridLineWidth 属性找 mGridLineWidth --> getGridLineWidth() --> XAxisRenderer 与 YAxisRenderer 类

那可以确定 绘制X Y轴的类 就是 XAxisRenderer 与 YAxisRenderer 而且在类中找到了对应的方法

2.2.3 绘制X轴刻度

观察平常的LineChart折线图,会发现我们需要的长刻度线与 网格线的位置相对应,所以可以模仿着网格线的绘制代码 绘制 刻度线

绘制网格线的源码如下

仿照上述两个方法,编写我们的刻度线绘制方法

首先,支持提供 方法 是否绘制刻度线 仿照 isDrawGridLinesEnabled() 找到其所在位置‘

在package com.github.mikephil.charting.components; AxisBase类中

我们可以 设置是否绘制刻度线

/**
 * 默认不绘制X Y轴刻度
 */
protected boolean mIsDrawScale = false;

public void setDrawScale(boolean mIsDrawScale) {this.mIsDrawScale = mIsDrawScale;
}
public boolean isDrawScale() {return mIsDrawScale;
}

然后回到  package com.github.mikephil.charting.renderer;包下 XAxisRenderer类中编写

/**
 * X轴制刻度线
 * @param c
 */
public void renderScaleLines(Canvas c) {if (!mXAxis.isDrawScale() || !mXAxis.isEnabled())return;
    if (mRenderGridLinesBuffer.length != mAxis.mEntryCount * 2) {mRenderGridLinesBuffer = new float[mXAxis.mEntryCount * 2];
    }float[] positions = mRenderGridLinesBuffer;
    for (int i = 0; i < positions.length; i += 2) {positions[i] = mXAxis.mEntries[i / 2];
        positions[i + 1] = mXAxis.mEntries[i / 2];
    }mTrans.pointValuesToPixel(positions); //获得X轴点对应的像素点位置 即坐标系位置
    for (int i = 0; i < positions.length - 2; i += 2) {//计算X轴两个值之间的间距/5   =  画布偏移量 即 刻度间距 还是默认5个刻度一组
        float offset = (positions[2] - positions[0]) / 5;
        drawScale(c, positions[i], offset);
    }
}/**
 * 绘制线
 */
protected void drawScale(Canvas canvas, float startX, float offset) {float topY = mViewPortHandler.contentTop(); //顶部X轴所在的位置
    float bottomY = mViewPortHandler.contentBottom(); //底部X轴所在的位置
    canvas.save();
    if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { //X轴位置在下方时
        for (int i = 0; i <= 5; i++) {canvas.save();
            canvas.translate(offset * i, 0);
            if (i % 5 == 0) {canvas.drawLine(startX, bottomY - 20, startX, bottomY, mAxisLinePaint);//画长刻度线
            } else {canvas.drawLine(startX, bottomY - 10, startX, bottomY, mAxisLinePaint);//画短刻度线
            }canvas.restore();
        }} else if (mXAxis.getPosition() == XAxisPosition.TOP) { //X轴位置在上方时
        for (int i = 0; i <= 5; i++) {canvas.save();
            canvas.translate(offset * i, 0);
            if (i % 5 == 0) {canvas.drawLine(startX, topY + 20, startX, topY, mAxisLinePaint);//画长刻度线
            } else {canvas.drawLine(startX, topY + 10, startX, topY, mAxisLinePaint);//画短刻度线
            }canvas.restore();
        }} else if (mXAxis.getPosition() == XAxisPosition.BOTH_SIDED) { //上下都有X轴时
        for (int i = 0; i <= 5; i++) {canvas.save();
            canvas.translate(offset * i, 0);
            if (i % 5 == 0) {//画长刻度线
                canvas.drawLine(startX, topY + 20, startX, topY, mAxisLinePaint);//顶部X轴的刻度
                canvas.drawLine(startX, bottomY - 20, startX, bottomY, mAxisLinePaint);//底部X轴的刻度
            } else {//画短刻度线
                canvas.drawLine(startX, topY + 10, startX, topY, mAxisLinePaint);//顶部X轴的刻度
                canvas.drawLine(startX, bottomY - 10, startX, bottomY, mAxisLinePaint);//底部X轴的刻度
            }canvas.restore();
        }}canvas.restore();
}

写好了在哪里调用呢?

同样点击源码绘制网格线的方法  renderGridLines(Canvas c) 可以查看到

在 package com.github.mikephil.charting.charts;包下 BarLineChartBase类中 onDraw方法中,第 210行 调用了 绘制XY轴 网格线 直线 绘制方法

因此我们的方法也应在此被调用

        mXAxisRenderer.renderAxisLine(canvas);
        mAxisRendererLeft.renderAxisLine(canvas);
        mAxisRendererRight.renderAxisLine(canvas);
/**********上面是源码的 下面是自己的方法***********************/
        mXAxisRenderer.renderScaleLines(canvas);

因为在绘制网格线时,使用的 画笔 mAxisLinePaint 是绘制X轴直线的画笔 所以可以保证刻度线的颜色 粗细 与X轴同步

当前效果

2.2.4 绘制Y轴刻度

绘制Y轴与绘制X轴类似

在 package com.github.mikephil.charting.renderer;包下 YAxisRenderer类中

/**
 * 绘制Y轴刻度线
 */
public void renderScaleLines(Canvas c) {if (!mYAxis.isDrawScale() || !mYAxis.isEnabled())return;
    float[] positions = getTransformedPositions();
    //因为 正常情况下 图表坐标轴在 左下方,所以此处 倒序 由下至上 绘制刻度
    for (int i = positions.length; i > 2; i -= 2) {float offset = (positions[i - 1] - positions[i - 3]) / 5; //偏移量
        drawScale(c, positions[i - 3], offset);
    }
}protected void drawScale(Canvas canvas, float startY, float offset) {float leftX = mViewPortHandler.contentLeft(); //Y轴在左边的位置
    float rightX = mViewPortHandler.contentRight();//Y轴在右边的位置
    canvas.save();
    if (mYAxis.getAxisDependency() == AxisDependency.LEFT) { //Y轴位置在左边时
        for (int i = 0; i <= 5; i++) {canvas.save();
            canvas.translate(0, offset * i);
            if (i % 5 == 0) {canvas.drawLine(leftX, startY, leftX + 20, startY, mAxisLinePaint);//画长刻度线
            } else {canvas.drawLine(leftX, startY, leftX + 10, startY, mAxisLinePaint);//画短刻度线
            }canvas.restore();
        }}if (mYAxis.getAxisDependency() == AxisDependency.RIGHT) { //Y轴位置在右边时
        for (int i = 0; i <= 5; i++) {canvas.save();
            canvas.translate(0, offset * i);
            if (i % 5 == 0) {canvas.drawLine(rightX, startY, rightX - 20, startY, mAxisLinePaint);//画长刻度线
            } else {canvas.drawLine(rightX, startY, rightX - 10, startY, mAxisLinePaint);//画短刻度线
            }canvas.restore();
        }}canvas.restore();
}

然后在 前面调用X轴绘制刻度线的位置 调用绘制Y轴刻度线的方法

        mXAxisRenderer.renderAxisLine(canvas);
        mAxisRendererLeft.renderAxisLine(canvas);
        mAxisRendererRight.renderAxisLine(canvas);
/**********上面是源码的 下面是自己的方法***********************/
        //绘制X轴刻度
        mXAxisRenderer.renderScaleLines(canvas);
        //绘制Y轴刻度
        mAxisRendererLeft.renderScaleLines(canvas);
        mAxisRendererRight.renderScaleLines(canvas);

最终效果如文章首页所展示的图

2.3 使用修改的源码

源码修改了,可以分别控制XY 轴是否绘制刻度线,在初始话设置 xAxis yAxis时设置即可,如下:

X轴绘制刻度,Y轴不绘制刻度

xAxis.setLabelCount(6, false);
//设置是否绘制刻度
xAxis.setDrawScale(true);
leftYAxis.setDrawScale(false);

XY轴都显示刻度

xAxis.setLabelCount(6, true);
//设置是否绘制刻度
xAxis.setDrawScale(true);
leftYAxis.setDrawScale(true);

效果图对比

左图 未设置绘制Y轴刻度,X轴设置非均分,最右不是完整的一个刻度,短刻度就无法绘制出来,如果只是炸死你长刻度还是无影响。

右图 X Y轴均绘制刻度,因X轴设置的是均分,都是完整的一个刻度,所以长短刻度都能绘制出来。

如果不想绘制短刻度线,可以在源码中添加一个boolean值,判断是否绘制短刻度即可,示例。

boolean isDrawShortLine = false;
if (i % 5 == 0) {canvas.drawLine(startX, bottomY - 20, startX, bottomY, mAxisLinePaint);//画长刻度线
} else if (isDrawShortLine){canvas.drawLine(startX, bottomY - 10, startX, bottomY, mAxisLinePaint);//画短刻度线
}

此时的效果

Y轴刻度与网格线重合了,难怪目标图设计 刻度线在外边,个人还是喜欢刻度线在里面,如果与网格线重合,不绘制即可。

如果刻度线非要绘制在外面,在绘制的时候 + - 符号对调一下即可,示例如下,XY轴绘制类似。

        if (mXAxis.getPosition() == XAxisPosition.BOTTOM) { //X轴位置在下方时
            for (int i = 0; i <= 5; i++) {canvas.save();
                canvas.translate(offset * i, 0);
                boolean isDrawShortLine = false;
                if (i % 5 == 0) {//刻度线在图表内部
//                    canvas.drawLine(startX, bottomY - 20, startX, bottomY, mAxisLinePaint);//画长刻度线
                    //刻度线在图表外面
                    canvas.drawLine(startX, bottomY + 20, startX, bottomY, mAxisLinePaint);//画长刻度线
                } else if (isDrawShortLine){
//                    canvas.drawLine(startX, bottomY - 10, startX, bottomY, mAxisLinePaint);//画短刻度线
                    canvas.drawLine(startX, bottomY + 10, startX, bottomY, mAxisLinePaint);//画短刻度线
                }canvas.restore();
            }

当前效果

2.4 修改X轴的位置

X,Y轴的刻度实现了,还差X轴位置的调整,需要从原点(0,0)开始

MPAndroidChart库为我们提供了几个方法可以在原点处绘制 一条线

leftYAxis.setDrawZeroLine(true); // draw a zero line
leftYAxis.setZeroLineColor(Color.GRAY);
leftYAxis.setZeroLineWidth(1f);

顺便在此修改一下Y轴的线条宽度、颜色。

leftYAxis.setAxisLineWidth(1f);
leftYAxis.setAxisLineColor(Color.GRAY);

此时的效果离目标图越来越近了

只需要将X轴的线条与刻度去掉,保留值的显示,然后在将绘制刻度线的方法,应用到与方法

 leftYAxis.setDrawZeroLine(true); 相关联的线条绘制类中即可。

经查找可以发现在 package com.github.mikephil.charting.renderer; 下的 YAxisRenderer类中可以找到

protected void drawZeroLine(Canvas c) 绘制原点的线条,修改此方法即可。

在绘制X轴刻度的时候,我们知道必须要知道X轴值的数量,才能绘制对应数量的刻度线,而zeroLine 是在Y轴中绘制的,所以

需要在传递一个XAxis对象给YAxisRenderer

和前面一样,模仿drawZeroLine 在YAxisRenderer 类中新建方法,

  /**
     * 绘制原点线的刻度线
     *
     * @param c
     * @param mXAxis
     */
    public void drawZeroLineScale(Canvas c, XAxis mXAxis) {if (!mYAxis.isDrawZeroLineEnabled()) {return;
        }MPPointD pos = mTrans.getPixelForValues(0f, 0f);
        if (mYAxis != null) {float[] positions = new float[mXAxis.mEntryCount * 2];
            for (int i = 0; i < positions.length; i += 2) {positions[i] = mXAxis.mEntries[i / 2];
                positions[i + 1] = mXAxis.mEntries[i / 2];
            }mTrans.pointValuesToPixel(positions); //获得X轴点对应的像素点位置 即坐标系位置
            for (int i = 0; i < positions.length - 2; i += 2) {//计算X轴两个值之间的间距/5   =  画布偏移量 即 刻度间距 还是默认5个刻度一组
                float offset = (positions[2] - positions[0]) / 5;
                drawZeroScale(c, (float) pos.y, positions[i], offset);
            }}}/**
     * 绘制原点线的刻度线
     *
     * @param zeroPosition 原点位置
     * @param startX       X轴起始位置
     * @param offset       偏移量
     */
    protected void drawZeroScale(Canvas canvas, float zeroPosition, float startX, float offset) {canvas.save();
        for (int i = 0; i <= 5; i++) {canvas.save();
            canvas.translate(offset * i, 0);
            boolean isDrawShortLine = false;
            if (i % 5 == 0) {//刻度线在图表内部
//                    canvas.drawLine(startX, zeroPosition - 20, startX, zeroPosition, mAxisLinePaint);//画长刻度线
                //刻度线在图表外面
                canvas.drawLine(startX, zeroPosition + 20, startX, zeroPosition, mAxisLinePaint);//画长刻度线
            } else if (isDrawShortLine) {
//                    canvas.drawLine(startX, zeroPosition - 10, startX, zeroPosition, mAxisLinePaint);//画短刻度线
                canvas.drawLine(startX, zeroPosition + 10, startX, zeroPosition, mAxisLinePaint);//画短刻度线
            }canvas.restore();
        }canvas.restore();
    }

然后在 package com.github.mikephil.charting.charts;包下的 BarLineChartBase 第 210行左右 调用我们新增的方法

/**********上面是源码的 下面是自己的方法***********************/
        //绘制X轴刻度
        mXAxisRenderer.renderScaleLines(canvas);
        //绘制Y轴刻度
        mAxisRendererLeft.renderScaleLines(canvas);
        mAxisRendererRight.renderScaleLines(canvas);
        //绘制原点线的刻度线
        mAxisRendererLeft.drawZeroLineScale(canvas, mXAxis);
        mAxisRendererRight.drawZeroLineScale(canvas, mXAxis);

源码修改部分完成。

然后在将X轴设置一下,在改下颜色就完成目标图的实现。

//设置是否绘制刻度
xAxis.setDrawScale(false);
//是否绘制X轴线
xAxis.setDrawAxisLine(false);

最终效果图如下。

三 总结

修改源码时,最好是新增方法,而不是在原有的方法中修改,改了一个地方可能会导致其他地方出现问题,而新增方法并未修

改到原有的东西。

MPAndroidChart 源码

Android图表控件MPAndroidChart——LineChart实现 XY轴、原点线的直尺刻度样式相关推荐

  1. android开发原点表框架,Android图表控件MPAndroidChart——LineChart实现 XY轴、原点线的直尺刻度样式...

    接上文: Android图表控件MPAndroidChart--曲线图LineChart的使用(多条曲线) 其他相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndro ...

  2. Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)

    目录 前言 本文涉及文章 其他相关文章 1.数据准备 1.1 数据来源 2.曲线展示 2.1 MPAndroidChart获取 2.2 数据对象获取 2.3 数据展示 3.曲线完善 3.1 图表背景. ...

  3. android好用的曲线图控件,Android图表控件MPAndroidChart——曲线图LineChart的使用(多条曲线)...

    发现最新的MPAndroidChart和以前版本的使用有一些差距,就写下了现在新版的使用方法 相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3. ...

  4. Android图表控件MPAndroidChart——BarChart实现多列柱状图以及堆积柱状图

    目录 前言 1. 数据准备 1.1 数据来源 2. 图表展示 2.1 MPAndroidChart获取 2.2 数据对象获取 2.3 数据展示 3. 柱状图外观完善 3.1 去掉图表外框,描述内容以及 ...

  5. Android图表控件MPAndroidChart的使用

    转载一篇Android图表控件MPAndroidChart的博客. 相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3.0) Android图表控 ...

  6. Android图表控件MPAndroidChart实现左右滑动以及联动

    前言 MPAndroidChart是一个功能强大的Android图表控件库,它实现了许多常见的图表效果.关于MPAndroidChart的使用文章已经很多了,这里不再详细介绍它的使用.当数据量过多时, ...

  7. C# winform使用scottplot图表控件快速入门设置XY轴缩放

    Hello大家好我是开箱测评小汪,在C#项目开发中使用图表控件,有时候我们希望放大或缩小图表控件来看数据细节和整体数据情况.所有本期课程将带介绍Scottplot图表控件如何来实现这个功能. 本期课程 ...

  8. android图表控件 坐标,android-charts 基于Java和Android开发的图形图表控件 | 李大仁博客...

    王晓龙 April 8th, 2014 at 09:44 | #1 我再github上看到了你写的控件,给了我很大启发,我现在在做K线图一类的图表,正好用到了您开发的这款控件,但是有些地方使用的不太舒 ...

  9. Android图表控件MPChart-柱状+折线组合图表基本使用

    一.效果图 双模式效果:柱形图加折线图,双y轴,从右向左滑动- 二.实现代码 1. 加入依赖 implementation 'com.github.PhilJay:MPAndroidChart:v3. ...

最新文章

  1. 中国消费者信息指数影响因素分析
  2. Obj-C的hello,world 2
  3. 3.8 Softmax 回归-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
  4. 未来的电子计算机作文500字,我的新计算机作文500字
  5. centos中的配置文件
  6. ISO C99中的一些扩展(草稿)
  7. kali linux解密栅栏密码,最详细bugku加密小白解法---持续更新!
  8. Django之验证码的实现,简单快捷的方法
  9. 迷宫问题 (dfs)
  10. java.lang.ArrayIndexOutOfBoundsException
  11. RadGrid Columns HeaderText
  12. Julia-数学运算和初等函数
  13. 判断当前环境在微信下,还是企业微信下
  14. 计算机科学之父--图灵
  15. 计算机共享w7系统文件共享,win7系统怎么共享文件 电脑一键共享文件方法教程...
  16. 《深度学习入门:基于Python的理论与实现》源代码
  17. 阿里飞猪个性化推荐:召回篇
  18. 知乎,挣钱?果然具有长尾效应
  19. SQLAlchemy黄金体验
  20. mysql数据库误删后能恢复吗_MySQL 数据库误删除后的数据恢复

热门文章

  1. Unity中暂停、继续播放、杀死、正放、倒放Dotween动画
  2. 五十分钟带你看遍C语言初阶语法(总纲)
  3. [shader]Unity 移动端海面
  4. 如何让arduino中的loop和Processing中的draw停下来
  5. 《一辈子够用的英语万用会话10000句》 PDF+MP3下载
  6. 高端电动汽车制造商蔚来使用Panasas ActiveStor存储加速产品设计和开发
  7. 电源系统分析之电源综合分析
  8. SGU 187.Twist and whirl - want to cheat
  9. 米Pad2Gpu降频修改
  10. 推动营销模式创新,华为云大数据解决方案加码企业数字化转型