MPAndroidChart的简单使用(中)

441 阅读3分钟

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。