I have been trying for a few hours now, to add a image inside a bar chart. The aim is to place an image above each of the bars in the chart.I am using the MPAndroidChart library for the purpose of drawing my charts. At the moment I am drawing a wind Bar chart and the code and the output is as follow.
private void setupBarChartWind(Forecast forecast)
{
BarChart chart = findViewById(R.id.barchart_wind);
chart.setVisibility(View.INVISIBLE);
List<BarEntry> entries = new ArrayList<BarEntry>();
String[] array = new String[NUM_HOURS];
for (int i=0;i<NUM_HOURS;i++) {
entries.add(new BarEntry(i,forecast.getHourly().getDataPoints().get(i).getWindSpeed().floatValue()));
Date date=new Date(forecast.getHourly().getDataPoints().get(i).getTime().getTime());
SimpleDateFormat df2 = new SimpleDateFormat("HH:mm a");
array[i] = df2.format(date);
}
int color = ContextCompat.getColor(getApplication(), R.color.white);
int color_transparent = ContextCompat.getColor(getApplication(), R.color.transparent_100);
mdataSet = new BarDataSet(entries, "Wind"); // add entries to dataset
mdataSet.setColor(color);
mdataSet.setValueTextColor(color_transparent);
BarData lineData = new BarData(mdataSet);
chart.setData(lineData);
chart.setBackgroundColor(getResources().getColor(R.color.transparent_weather_50));
chart.animate();
XAxis xAxis = chart.getXAxis();
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setTextSize(10f);
xAxis.setTextColor(Color.WHITE);
xAxis.setLabelCount(6);
xAxis.setValueFormatter(new MyXAxisValueFormatter(array));
YAxis yAxis = chart.getAxisLeft();
yAxis.setTextSize(12f); // set the text size
yAxis.setTextColor(Color.WHITE);
yAxis.setGranularity(1f); // interval 1
chart.getDescription().setText("Wind");
chart.getData().setHighlightEnabled(false);
chart.setVisibility(View.VISIBLE);
chart.getXAxis().setDrawGridLines(false);
chart.getAxisLeft().setDrawGridLines(false);
chart.getAxisRight().setDrawGridLines(false);
chart.animateX(2000);
chart.invalidate();
}
I have found i few links: MPAndroidChart: add custom image inside bars ,
How do MPAndroidChart renderers work and how do I write a custom renderer? and tried to read the documents on how the renders work, from the above mentioned resources I have written the following code to implement the desired behavior.
public class BarChartImageRenderer extends BarChartRenderer {
private final Bitmap imageToRender;
public BarChartImageRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Bitmap imageToRender) {
super(chart, animator, viewPortHandler);
this.imageToRender=imageToRender;
}
@Override
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
super.drawDataSet(c, dataSet, index);
drawBarImages(c, dataSet, index);
}
protected void drawBarImages(Canvas c, IBarDataSet dataSet, int index) {
BarBuffer buffer = mBarBuffers[index];
float left;
float right;
float top;
float bottom;
for (int j = 0; j < buffer.buffer.length * mAnimator.getPhaseX(); j += 4) {
left = buffer.buffer[j];
right = buffer.buffer[j + 2];
top = buffer.buffer[j + 1];
bottom = buffer.buffer[j + 3];
float x = (left + right) / 2f;
if (!mViewPortHandler.isInBoundsRight(x))
break;
if (!mViewPortHandler.isInBoundsY(top)
|| !mViewPortHandler.isInBoundsLeft(x))
continue;
BarEntry entry = dataSet.getEntryForIndex(j / 4);
float val = entry.getY();
final Bitmap scaledBarImage = scaleBarImage(buffer,imageToRender);
int starWidth = scaledBarImage.getWidth();
int starOffset = starWidth / 2;
drawImage(c, scaledBarImage, x - starOffset, top);
}
}
private Bitmap scaleBarImage(BarBuffer buffer, Bitmap image) {
float firstLeft = buffer.buffer[0];
float firstRight = buffer.buffer[2];
int firstWidth = (int) Math.ceil(firstRight - firstLeft);
return Bitmap.createScaledBitmap(image, firstWidth, firstWidth, false);
}
protected void drawImage(Canvas c, Bitmap image, float x, float y) {
if (image != null) {
c.drawBitmap(image, x, y, null);
}
}
}
But unfortunately I keep getting the following error:
2019-03-09 13:31:55.555 13955-13955/com.example.homeactivity E/AndroidRuntime: FATAL EXCEPTION: main
Process: com.example.homeactivity, PID: 13955
java.lang.NullPointerException: Attempt to read from null array
at com.github.mikephil.charting.renderer.BarChartRenderer.drawDataSet(BarChartRenderer.java:138)
at com.example.homeactivity.Trending.TrendingActivity$BarChartImageRenderer.drawDataSet(TrendingActivity.java:447)
at com.github.mikephil.charting.renderer.BarChartRenderer.drawData(BarChartRenderer.java:82)
at com.github.mikephil.charting.charts.BarLineChartBase.onDraw(BarLineChartBase.java:237)
I can't seem to figure out why it keeps on throwing a null array error? Any pointers to how I could solve this would be appreciated...