Android图表控件MPAndroidChart——源码修改实现曲线图X轴直尺刻度样式
2017-11-15 10:36
1011 查看
相关文章:
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轴刻度,如下所示
而MPAndroidChart的XY轴确是这样,没有长短刻度
没有找到相关方法设置显示类似直尺样式的刻度(若有相关方法可实现,请告诉我),所以只有修改下源码
先上最终效果图,修改源码后得到的效果如下所示
修改源码之前首先自己在View中画出刻度,然后找到X轴的绘制代码,最后将自己写的方法 融入进去就好了
一 .画刻度线
1.画刻度线的方式(多种方式,说下我的方式)
先画一条刻度线,然后平移画布一段距离(即刻度线间的间距),在画短刻度线(坐标轴未变,只是画布位置变了,至使表面上看起来线位置变了)
2.画刻度线
手机坐标轴:
画刻度:
新建MyScaleView 重写 onDraw()方法
最后应用MyScaleView 效果如下
二.MPAndroidChart库中画 X Y 轴刻度线
1.下载源码:https://github.com/PhilJay/MPAndroidChart/releases
点击 Downloads Source code(zip) 我下载的版本为v3.0.2 解压后里面的MPChartLib即为MPAndroidChart库源码
2.寻找X Y轴的绘制类
说下我的思路
首先找到 X轴 XAxis 并没有什么相关绘制代码
接着找到父类 AxisBase 发现 X Y 轴都继承于该类,那肯定和这类相关了
然后发现 AxisBase 类下定义了 相关属性 和 绘制图形相关
沿着 mGridLineWidth 属性找 mGridLineWidth --> getGridLineWidth() --> XAxisRenderer 与 YAxisRenderer 类
那可以确定 绘制X Y轴的类 就是 XAxisRenderer 与 YAxisRenderer 而且在类中找到了对应的方法
3.绘制X轴
观察平常的LineChart折线图,会发现我们需要的长刻度线与 网格线的位置想对应,所以可以模仿着网格线的绘制代码 绘制 刻度线
绘制网格线的源码如下
仿照上述两个方法,编写我们的刻度线绘制方法
首先,支持提供 方法 是否绘制刻度线 仿照 isDrawGridLinesEnabled() 找到其所在位置‘
在package com.github.mikephil.charting.components; AxisBase类中
我们可以 设置是否绘制刻度线
然后回到 package com.github.mikephil.charting.renderer;包下 XAxisRenderer类中编写
写好了在哪里调用呢?
同样点击源码绘制网格线的方法 renderGridLines(Canvas c) 可以查看到
在 package com.github.mikephil.charting.charts;包下 BarLineChartBase类中 第 210行 调用了 绘制XY轴 网格线 直线 绘制方法
因此我们的方法也应在此被调用
因为在绘制网格线时,使用的 画笔 mAxisLinePaint 是绘制X轴直线的画笔 所以可以保证刻度线的颜色 粗细 与X轴同步
最后的效果
4.绘制Y轴
绘制Y轴与绘制X轴类似
在 package com.github.mikephil.charting.renderer;包下 YAxisRenderer类中
然后在 前面调用X轴绘制刻度线的位置 调用绘制Y轴刻度线的方法
最终效果如文章开始所展示的图
三 总结
观察一下MPAndroidChart 源码的包名 看名字就可以知道功能,需要修改哪些东西就去对应的包下找
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轴刻度,如下所示
而MPAndroidChart的XY轴确是这样,没有长短刻度
没有找到相关方法设置显示类似直尺样式的刻度(若有相关方法可实现,请告诉我),所以只有修改下源码
先上最终效果图,修改源码后得到的效果如下所示
修改源码之前首先自己在View中画出刻度,然后找到X轴的绘制代码,最后将自己写的方法 融入进去就好了
一 .画刻度线
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 效果如下
二.MPAndroidChart库中画 X Y 轴刻度线
1.下载源码:https://github.com/PhilJay/MPAndroidChart/releases
点击 Downloads Source code(zip) 我下载的版本为v3.0.2 解压后里面的MPChartLib即为MPAndroidChart库源码
2.寻找X Y轴的绘制类
说下我的思路
首先找到 X轴 XAxis 并没有什么相关绘制代码
接着找到父类 AxisBase 发现 X Y 轴都继承于该类,那肯定和这类相关了
然后发现 AxisBase 类下定义了 相关属性 和 绘制图形相关
沿着 mGridLineWidth 属性找 mGridLineWidth --> getGridLineWidth() --> XAxisRenderer 与 YAxisRenderer 类
那可以确定 绘制X Y轴的类 就是 XAxisRenderer 与 YAxisRenderer 而且在类中找到了对应的方法
3.绘制X轴
观察平常的LineChart折线图,会发现我们需要的长刻度线与 网格线的位置想对应,所以可以模仿着网格线的绘制代码 绘制 刻度线
绘制网格线的源码如下
仿照上述两个方法,编写我们的刻度线绘制方法
首先,支持提供 方法 是否绘制刻度线 仿照 isDrawGridLinesEnabled() 找到其所在位置‘
在package com.github.mikephil.charting.components; AxisBase类中
我们可以 设置是否绘制刻度线
protected boolean mIsDrawScale = true; public void setDrawScale(boolean mIsDrawScale) { this.mIsDrawScale = mIsDrawScale; } public boolean isDrawScale() { return mIsDrawScale; }
然后回到 package com.github.mikephil.charting.renderer;包下 XAxisRenderer类中编写
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[i + 2] - positions[i]) / 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 == 0 || i == 5) { 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 == 0 || i == 5) { 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 == 0 || i == 5) { //画长刻度线 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类中 第 210行 调用了 绘制XY轴 网格线 直线 绘制方法
因此我们的方法也应在此被调用
mXAxisRenderer.renderAxisLine(canvas); mAxisRendererLeft.renderAxisLine(canvas); mAxisRendererRight.renderAxisLine(canvas); mXAxisRenderer.renderGridLines(canvas); mAxisRendererLeft.renderGridLines(canvas); mAxisRendererRight.renderGridLines(canvas); /**********上面是源码的 下面是自己的方法***********************/ mXAxisRenderer.renderScaleLines(canvas);
因为在绘制网格线时,使用的 画笔 mAxisLinePaint 是绘制X轴直线的画笔 所以可以保证刻度线的颜色 粗细 与X轴同步
最后的效果
4.绘制Y轴
绘制Y轴与绘制X轴类似
在 package com.github.mikephil.charting.renderer;包下 YAxisRenderer类中
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 == 0 || i == 5) { 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 == 0 || i == 5) { canvas.drawLine(rightX, startY, rightX - 20, startY, mAxisLinePaint);//画长刻度线 } else { canvas.drawLine(rightX, startY, rightX - 10, startY, mAxisLinePaint);//画短刻度线 } canvas.restore(); } } canvas.restore(); }
然后在 前面调用X轴绘制刻度线的位置 调用绘制Y轴刻度线的方法
mXAxisRenderer.renderScaleLines(canvas); mAxisRendererLeft.renderScaleLines(canvas); mAxisRendererRight.renderScaleLines(canvas);
最终效果如文章开始所展示的图
三 总结
观察一下MPAndroidChart 源码的包名 看名字就可以知道功能,需要修改哪些东西就去对应的包下找
相关文章推荐
- Android图表控件MPAndroidChart——曲线图LineChart(多条曲线)动态添加数据^a!HsMa0cWDc
- Android中修改源码实现AutoCompeteTextView控件的模糊匹配
- Android图表控件MPAndroidChart——曲线图LineChart的使用(多条曲线)p8qjA6jN9Z3n
- Android中修改源码实现AutoCompeteTextView控件的模糊匹配
- Android中修改源码实现AutoCompeteTextView控件的模糊匹配
- Android图表控件MPAndroidChart之曲线图的实现
- Android图表控件MPAndroidChart——曲线图LineChart的使用(多条曲线)
- Android源码中控件样式资源
- android仿iPhone滚轮控件实现及源码分析(1)
- android仿iPhone滚轮控件实现及源码分析(一)
- android后台截屏实现(2)--screencap源码修改
- Android之修改系统控件的样式
- 在android中利用多线程实现对控件的更新(动态修改文本框中的值)。简述原理并上传代码。 .
- Android 4.2 通过修改FrameWork源码实现动态隐藏导航栏,实现全屏
- 图表曲线Teechart——采用Cdib类和内存映射文件加快TChart控件画图速度的实现方法
- Android自定义组件之日历控件-精美日历实现(内容、样式可扩展)
- android仿iPhone滚轮控件实现及源码分析(一)
- android仿iPhone滚轮控件实现及源码分析(2)
- 【转】android仿iPhone滚轮控件实现及源码分析(一)
- android仿iPhone滚轮控件实现及源码分析(二)