android开发原点表框架,Android图表控件MPAndroidChart——LineChart实现 XY轴、原点线的直尺刻度样式...
接上文:
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轴、原点线的直尺刻度样式...相关推荐
- Android图表控件MPAndroidChart——LineChart实现 XY轴、原点线的直尺刻度样式
接上文: Android图表控件MPAndroidChart--曲线图LineChart的使用(多条曲线) 其他相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndro ...
- C# winform使用scottplot图表控件快速入门设置XY轴缩放
Hello大家好我是开箱测评小汪,在C#项目开发中使用图表控件,有时候我们希望放大或缩小图表控件来看数据细节和整体数据情况.所有本期课程将带介绍Scottplot图表控件如何来实现这个功能. 本期课程 ...
- Android图表控件MPAndroidChart——曲线图LineChart的使用(财富收益图)
目录 前言 本文涉及文章 其他相关文章 1.数据准备 1.1 数据来源 2.曲线展示 2.1 MPAndroidChart获取 2.2 数据对象获取 2.3 数据展示 3.曲线完善 3.1 图表背景. ...
- Android图表控件MPAndroidChart——BarChart实现多列柱状图以及堆积柱状图
目录 前言 1. 数据准备 1.1 数据来源 2. 图表展示 2.1 MPAndroidChart获取 2.2 数据对象获取 2.3 数据展示 3. 柱状图外观完善 3.1 去掉图表外框,描述内容以及 ...
- android好用的曲线图控件,Android图表控件MPAndroidChart——曲线图LineChart的使用(多条曲线)...
发现最新的MPAndroidChart和以前版本的使用有一些差距,就写下了现在新版的使用方法 相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3. ...
- Android图表控件MPAndroidChart的使用
转载一篇Android图表控件MPAndroidChart的博客. 相关文章: Android图表控件MPAndroidChart的简单介绍(MPAndroidChart3.0) Android图表控 ...
- Android图表控件MPAndroidChart实现左右滑动以及联动
前言 MPAndroidChart是一个功能强大的Android图表控件库,它实现了许多常见的图表效果.关于MPAndroidChart的使用文章已经很多了,这里不再详细介绍它的使用.当数据量过多时, ...
- Android开发RecyclerView刷新后item里面控件动画
项目中有个列表的item中有点赞动画,之前我用的列表框架是继承listview的,动画用起来一点问题都没有,现在列表框架是继承用的recyclerView,动画就卡主,百思不得其姐. 解决方法: 1. ...
- 如何用图表控件实现点击图例图标隐藏图表序列
为了提高开发效率,第三方商用图表控件越来越被程序员广泛使用,由于第三方商用控件产品的可重用性,可以帮助企业节约GUI工程师的压力而实现灵活,绚丽的图表. 在阅读以下文章之前先下载安装试用版: Fusi ...
最新文章
- C语言编译全过程(转贴)
- 《网络攻防实践》第七周作业
- 【已解决】Could not find resource jdbc.properties
- 利用Linux系统生成随机密码的10种方法
- 点乘叉乘坐标公式_点积与叉乘的运算与物理意义
- 努比亚连续按下android版本,虚惊一场!努比亚Z17的Android 9.0真的不远了
- hooks的常用Api
- python 简历处理_按照这个方式学Python,老板把垃圾桶里的简历舔回来:月薪50000...
- Crontab作业时间设置
- php 生产环境调错
- k8s使用volume将ConfigMap作为文件或目录直接挂载_Kubernetes in Action 06. 卷:将磁盘挂载到容器...
- 高德天气 php,天气查询-API文档-开发指南-Web服务 API | 高德地图API
- 【单目标优化求解】基于matlab遗传算法求解单目标优化问题【含Matlab源码 1320期】
- 【Eclipse】Eclipse使用技巧
- 如何解决RS485 通讯接口被主站占用的问题
- 浏览器怎么导入导出|删除书签,方法步骤来咯
- 蚂蚁金服 Service Mesh 大规模落地系列 - 网关篇
- html代码标签优化与提速,HTML代码标签优化与提速
- 基于FPGA数字混频器的设计(1)
- 部署外网网站(二)——宝塔搭建服务器