2.实现圆角柱状图并且将柱状图的icon固定到柱状图底部
要实现圆角的柱状图,需要重写绘制柱状图的方法来实现。MPAndroidChart绘制的方法都放在renderer包下面,找到BarChartRenderer类,其中drawDataSet的方法负责柱状图的绘制。该方法如下:
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
...... //这里一大堆都是柱状图的测量和画笔的定义,下面是绘制柱状图的主要方法
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
if (drawBorder) {
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mBarBorderPaint);
}
}
}
buffer中存放left,top,right,bottom四个顶点的位置信息,要实现圆角柱状图,直接给一个圆角值即可,重写方法如下:
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
......
//改成画圆角矩形,将四个顶点信息存放进矩形中
val rectF = RectF(
buffer.buffer[j],
buffer.buffer[j + 1],
buffer.buffer[j + 2],
buffer.buffer[j + 3]
)
c!!.drawRoundRect(rectF, 80f, 80f, mRenderPaint);
if (drawBorder) {
c!!.drawRoundRect(rectF, 80f, 80f, mBarBorderPaint);
}
}
注意如果有点击高亮的功能,负责高亮绘制的drawHighlighted方法也需要重写。高亮的绘制是在柱状图的基础上再叠加一层图形,如果不重写drawHighlighted方法,柱状图的高亮状态不是圆角。高亮方法的修改同理,如下:
override fun drawHighlighted(c: Canvas?, indices: Array<out Highlight>?) {
......
// c!!.drawRect(mBarRect, mHighlightPaint) //这是原本的绘制方法,替换为下面的方法即可
c!!.drawRoundRect(mBarRect, 80f, 80f, mHighlightPaint)
}
}
如何将重写的MyBarChartRenderer应用到自己项目中。BarChartRenderer在BarChart中的使用如下:
public class BarChart extends BarLineChartBase<BarData> implements BarDataProvider {
......
@Override
protected void init() {
super.init();
mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); //只有这一句
setHighlighter(new BarHighlighter(this));
getXAxis().setSpaceMin(0.5f);
getXAxis().setSpaceMax(0.5f);
}
......
}
那就很好办啦,定义一个MyBarChart类继承BarChart,重写init方法,将自己的MyBarChartRenderer赋给MyBarChart的mRenderer,mRenderer同志肩扛整个柱状图的渲染工作,如下:
class MyBarChart : BarChart {
constructor(context: Context) : this(context, null)
constructor(context: Context, attrs: AttributeSet? = null) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet? = null, defStyle: Int)
: super(context, attrs, defStyle)
override fun init() {
super.init()
mRenderer = MyBarChartRenderer(this,mAnimator,mViewPortHandler) //
}
}
使用的时候,只需要:
<MyBarChart
android:id="@+id/report_bc_step"
....../>
这样便可实现圆角的柱状图。
柱状图的icon默认显示在柱状图顶部,和柱状图的value标签值一起绘制。
当要设置icon的位置时,可以通过对BarDataSet的iconsOffset进行设值。这里需求是要把icon固定绘制在柱状图的底部,因为在外面没有办法拿到柱状图的高度,需要从里面进行设置。同样也是在BarChartRenderer中操作。drawValues方法负责绘制标签值和icon,
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
float px = x;
float py = val >= 0 ?
(buffer.buffer[j + 1] + posOffset) :
(buffer.buffer[j + 3] + negOffset);
px += iconsOffset.x;
py += iconsOffset.y;
Utils.drawImage(
c,
icon,
(int)px,
(int)py,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
在drawValues中,这段代码多次出现,负责icon的绘制,其中buffer.buffer[j + 3]是柱状图的高度,将其修改如下:
if (entry.icon != null && dataSet.isDrawIconsEnabled) {
val icon = entry.icon
var px = x
//修改y使icon居于柱状图底部
var py = buffer.buffer[j + 3] - Utils.convertDpToPixel(20f)
// if (`val` >= 0) buffer.buffer[j + 1] + posOffset else buffer.buffer[j + 3] + negOffset
px += iconsOffset.x
py += iconsOffset.y
Utils.drawImage(
c,
icon,
px.toInt(),
py.toInt(),
icon.intrinsicWidth,
icon.intrinsicHeight
)
}
这样便可固定柱状图的icon。