MPAndroidChart 默认的选中高亮效果如下:
只是颜色加深,然后设计想要实现下面这种效果:
类似阴影效果,且显示的宽度需要增加。
一、MPAndroidChart 是否支持
查看该框架对外的接口,发现下面两个方法:
BarDataSet set1 = new BarDataSet(yValues, "");
set1.setHighLightColor(ContextCompat.getColor(this, R.color.black));
set1.setHighLightAlpha(40);
只能修改高亮颜色和透明度,没有办法修改宽度和高度,无法达到我们想要的效果。
没有办法,只能先查看源码是如何实现,然后尝试去修改了。
二、查看源码实现
从setHighLightAlpha()
方法入手:
//BarDataSet.java
public void setHighLightAlpha(int alpha) {
mHighLightAlpha = alpha;
}
@Override
public int getHighLightAlpha() {
return mHighLightAlpha;
}
查看 getHighLightAlpha()
方法在哪里调用:
//BarChartRenderer.java
@Override
public void drawHighlighted(Canvas c, Highlight[] indices) {
BarData barData = mChart.getBarData();
for (Highlight high : indices) {
IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
......
prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
setHighlightDrawPos(high, mBarRect);
//原来高亮背景就是绘制了一个矩形
c.drawRect(mBarRect, mHighlightPaint);
}
}
从源码中可以看出,点击效果就是通过点击位置,重新绘制一个矩形。
所以重点就是 mBarRect
的赋值。
//BarChartRenderer.java
protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf, Transformer trans) {
float left = x - barWidthHalf;
float right = x + barWidthHalf;
float top = y1;
float bottom = y2;
mBarRect.set(left, top, right, bottom);
trans.rectToPixelPhase(mBarRect, mAnimator.getPhaseY());
}
可以看到只要复写该方法,修改参数,就可以修改高亮矩形框的宽高。
三、代码实现
3.1 重写 BarChartRenderer 类
查看源码,可以发现 BarChartRenderer
的初始化位置,且支持自定义:
//BarChart.java
@Override
protected void init() {
super.init();
//初始化地方
mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler);
setHighlighter(new BarHighlighter(this));
getXAxis().setSpaceMin(0.5f);
getXAxis().setSpaceMax(0.5f);
}
//支持开发者自定义
public void setRenderer(DataRenderer renderer) {
if (renderer != null)
mRenderer = renderer;
}
自定义 BarChartRenderer
:
public class TestBarChartRenderer extends BarChartRenderer {
private Transformer transformer;
public TestBarChartRenderer(
BarDataProvider chart,
ChartAnimator animator,
ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
@Override
protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf,
Transformer trans) {
transformer = trans;
//修改高亮效果的高度和宽度,getYChartMax获取的就是表格的最大值
super.prepareBarHighlight(x, mChart.getYChartMax(), y2, barWidthHalf + 0.2f, trans);
}
}
//设置自定义Renderer
barChart.setRenderer(
new TestBarChartRenderer(barChart, barChart.getAnimator(), barChart.getViewPortHandler()));
//点击整条数据高亮
barChart.setHighlightFullBarEnabled(true);
上面修改后虽然效果实现了,但是会导致一个问题,点击数据后,所有的数据的标记视图都在同一高度:
查看源码发现:
//BarChartRenderer.java
@Override
public void drawHighlighted(Canvas c, Highlight[] indices) {
BarData barData = mChart.getBarData();
for (Highlight high : indices) {
IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
......
prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
//修改高亮数据
setHighlightDrawPos(high, mBarRect);
//原来高亮背景就是绘制了一个矩形
c.drawRect(mBarRect, mHighlightPaint);
}
}
protected void setHighlightDrawPos(Highlight high, RectF bar) {
//这个位置会影响标记视图的显示位置
high.setDraw(bar.centerX(), bar.top);
}
所以在 prepareBarHighlight()
方法中修改完数据后,需要在 setHighlightDrawPos()
方法中还原真实的数据。最终代码如下:
public class TestBarChartRenderer extends BarChartRenderer {
private Transformer transformer;
public TestBarChartRenderer(
BarDataProvider chart,
ChartAnimator animator,
ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
@Override
protected void prepareBarHighlight(float x, float y1, float y2, float barWidthHalf,
Transformer trans) {
transformer = trans;
//修改高亮背景的高度和宽度
super.prepareBarHighlight(x, mChart.getYChartMax(), y2, barWidthHalf + 0.2f, trans);
}
@Override
protected void setHighlightDrawPos(Highlight high, RectF bar) {
if (transformer != null) {
//还原真实的点击数据
float barWidthHalf = mChart.getBarData().getBarWidth() / 2f;
float x = high.getX();
RectF rectF = new RectF();
rectF.set(x - barWidthHalf, high.getY(), x + barWidthHalf, 0f);
transformer.rectToPixelPhase(rectF, mAnimator.getPhaseY());
super.setHighlightDrawPos(high, rectF);
} else {
super.setHighlightDrawPos(high, bar);
}
}
}
柱状图的实现可以参考:
MPAndroidChart实现堆叠柱状图
MPAndroidChart 自定义 MarkerView