接上文:

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 classMyScaleView extendsView {

privatePaint scalePaint;publicMyScaleView(Context context) {

this(context, null);}

publicMyScaleView(Context context,@NullableAttributeSet attrs) {

this(context,attrs,0);}

publicMyScaleView(Context context,@NullableAttributeSet attrs, intdefStyleAttr) {

super(context,attrs,defStyleAttr);initPaint();}

private voidinitPaint() {

scalePaint= newPaint();scalePaint.setAntiAlias(true);scalePaint.setColor(Color.RED);scalePaint.setStrokeWidth(2);scalePaint.setStyle(Paint.Style.FILL);scalePaint.setDither(true);}

@Overrideprotected voidonDraw(Canvas canvas) {

super.onDraw(canvas);drawScale(canvas);}

private voiddrawScale(Canvas canvas) {

intscaleGroup = 5;//默认1个长刻度间隔4个短刻度,加起来一组5intmScaleCount = 101;//刻度的总个数canvas.save();intstartX = 30;intstartY = 500;//即在坐标轴(30,500)处开始画刻度线for(inti = 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 booleanmIsDrawScale= false;public voidsetDrawScale(booleanmIsDrawScale) {

this.mIsDrawScale= mIsDrawScale;}

public booleanisDrawScale() {

returnmIsDrawScale;}

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

/***绘X轴制刻度线*@paramc*/public voidrenderScaleLines(Canvas c) {

if(!mXAxis.isDrawScale() || !mXAxis.isEnabled())

return;if(mRenderGridLinesBuffer.length!= mAxis.mEntryCount* 2) {

mRenderGridLinesBuffer= new float[mXAxis.mEntryCount* 2];}

float[] positions = mRenderGridLinesBuffer;for(inti = 0;i < positions.length;i += 2) {

positions[i] = mXAxis.mEntries[i / 2];positions[i + 1] = mXAxis.mEntries[i / 2];}

mTrans.pointValuesToPixel(positions);//获得X轴点对应的像素点位置 即坐标系位置for(inti = 0;i < positions.length- 2;i += 2) {

//计算X轴两个值之间的间距/5 =画布偏移量 即 刻度间距 还是默认5个刻度一组floatoffset = (positions[2] - positions[0]) / 5;drawScale(c,positions[i],offset);}

}

/***绘制线*/protected voiddrawScale(Canvas canvas, floatstartX, floatoffset) {

floattopY = mViewPortHandler.contentTop();//顶部X轴所在的位置floatbottomY = mViewPortHandler.contentBottom();//底部X轴所在的位置canvas.save();if(mXAxis.getPosition() == XAxisPosition.BOTTOM) { //X轴位置在下方时for(inti = 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(inti = 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(inti = 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 voidrenderScaleLines(Canvas c) {

if(!mYAxis.isDrawScale() || !mYAxis.isEnabled())

return;float[] positions = getTransformedPositions();//因为 正常情况下 图表坐标轴在 左下方,所以此处 倒序 由下至上 绘制刻度for(inti = positions.length;i > 2;i -= 2) {

floatoffset = (positions[i - 1] - positions[i - 3]) / 5;//偏移量drawScale(c,positions[i - 3],offset);}

}

protected voiddrawScale(Canvas canvas, floatstartY, floatoffset) {

floatleftX = mViewPortHandler.contentLeft();//Y轴在左边的位置floatrightX = mViewPortHandler.contentRight();//Y轴在右边的位置canvas.save();if(mYAxis.getAxisDependency() == AxisDependency.LEFT) { //Y轴位置在左边时for(inti = 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(inti = 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值,判断是否绘制短刻度即可,示例。

booleanisDrawShortLine = 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(inti = 0;i <= 5;i++) {

canvas.save();canvas.translate(offset * i,0);booleanisDrawShortLine = 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 lineleftYAxis.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类中新建方法,

/***绘制原点线的刻度线**@paramc*@parammXAxis*/public voiddrawZeroLineScale(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(inti = 0;i < positions.length;i += 2) {

positions[i] = mXAxis.mEntries[i / 2];positions[i + 1] = mXAxis.mEntries[i / 2];}

mTrans.pointValuesToPixel(positions);//获得X轴点对应的像素点位置 即坐标系位置for(inti = 0;i < positions.length- 2;i += 2) {

//计算X轴两个值之间的间距/5 =画布偏移量 即 刻度间距 还是默认5个刻度一组floatoffset = (positions[2] - positions[0]) / 5;drawZeroScale(c,(float) pos.y,positions[i],offset);}

}

}

/***绘制原点线的刻度线**@paramzeroPosition原点位置*@paramstartXX轴起始位置*@paramoffset偏移量*/protected voiddrawZeroScale(Canvas canvas, floatzeroPosition, floatstartX, floatoffset) {

canvas.save();for(inti = 0;i <= 5;i++) {

canvas.save();canvas.translate(offset * i,0);booleanisDrawShortLine = 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开发原点表框架,Android图表控件MPAndroidChart——LineChart实现 XY轴、原点线的直尺刻度样式...相关推荐

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

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

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

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

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

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

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

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

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

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

  6. Android图表控件MPAndroidChart的使用

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

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

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

  8. Android开发RecyclerView刷新后item里面控件动画

    项目中有个列表的item中有点赞动画,之前我用的列表框架是继承listview的,动画用起来一点问题都没有,现在列表框架是继承用的recyclerView,动画就卡主,百思不得其姐. 解决方法: 1. ...

  9. 如何用图表控件实现点击图例图标隐藏图表序列

    为了提高开发效率,第三方商用图表控件越来越被程序员广泛使用,由于第三方商用控件产品的可重用性,可以帮助企业节约GUI工程师的压力而实现灵活,绚丽的图表. 在阅读以下文章之前先下载安装试用版: Fusi ...

最新文章

  1. C语言编译全过程(转贴)
  2. 《网络攻防实践》第七周作业
  3. 【已解决】Could not find resource jdbc.properties
  4. 利用Linux系统生成随机密码的10种方法
  5. 点乘叉乘坐标公式_点积与叉乘的运算与物理意义
  6. 努比亚连续按下android版本,虚惊一场!努比亚Z17的Android 9.0真的不远了
  7. hooks的常用Api
  8. python 简历处理_按照这个方式学Python,老板把垃圾桶里的简历舔回来:月薪50000...
  9. Crontab作业时间设置
  10. php 生产环境调错
  11. k8s使用volume将ConfigMap作为文件或目录直接挂载_Kubernetes in Action 06. 卷:将磁盘挂载到容器...
  12. 高德天气 php,天气查询-API文档-开发指南-Web服务 API | 高德地图API
  13. 【单目标优化求解】基于matlab遗传算法求解单目标优化问题【含Matlab源码 1320期】
  14. 【Eclipse】Eclipse使用技巧
  15. 如何解决RS485 通讯接口被主站占用的问题
  16. 浏览器怎么导入导出|删除书签,方法步骤来咯
  17. 蚂蚁金服 Service Mesh 大规模落地系列 - 网关篇
  18. html代码标签优化与提速,HTML代码标签优化与提速
  19. 基于FPGA数字混频器的设计(1)
  20. 部署外网网站(二)——宝塔搭建服务器

热门文章

  1. Fatfs文件系统二次f_open返回值为FR_DISK_ERR的问题
  2. HTML用画布实现刮刮卡,利用HTML5的画布Canvas实现刮刮卡效果_javascript技巧
  3. Android版的疯狂猜图游戏源码完整版分享
  4. iOS 美女波浪图~ demo
  5. 《听我说谢谢你》简谱
  6. 最近工作中遇到的8个问题
  7. 我简历上的项目好 Low,怎么破?
  8. Python排列组合的计算方法
  9. 门口养了只孔雀的那家公司,办公室里还有 7、8 种小动物
  10. 关于心理的二十五种倾向(查理·芒格)-2