Line Chart Implementation —with MPAndroidChart

Srinivasa Rao Makkena
4 min readMay 25, 2020

--

We need to implement the charts as part of our business requirements or for personal app implementation. If I choose eCommerce app. We would like to display sales flow chart in the past few days for the business to understand how the sales are effecting due to situations around. There are many 3rd party libraries available to work around. But, this MPAndroidChart library have more customer base, documentation and support.

Let’s dive deep in

Here I am going to implement below kind of graph.

  1. Library dependency (Check for the advanced versions if available)
implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'

2. View

<com.github.mikephil.charting.charts.LineChart
android:id="@+id/reportingChart"
android:layout_width="match_parent"
android:layout_height="230dp"
android:layout_marginLeft="16dp"
android:layout_marginRight="16dp"
android:layout_marginTop="8dp"
android:background="@color/white"
android:elevation="10dp"
/>

Once we have view and library, we need data to represent that and different ways to represent and define X and Y axis and representation of boundaries etc.

Access this view from Activity as below

volumeReportChart = findViewById(R.id.reportingChart);
volumeReportChart.setTouchEnabled(true);
volumeReportChart.setPinchZoom(true);

The above statements make that chart to zoom in and zoom out to check deeper trends. Passing data to the chart as in below method.

To draw limit lines like dark dotted line in the above chart.

We can set this limit line’s position and color etc.

LimitLine ll1 = new LimitLine(30f,"Title");
ll1.setLineColor(getResources().getColor(R.color.greyish_brown));
ll1.setLineWidth(4f);
ll1.enableDashedLine(10f, 10f, 0f);
ll1.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_BOTTOM);
ll1.setTextSize(10f);

LimitLine ll2 = new LimitLine(35f, "");
ll2.setLineWidth(4f);
ll2.enableDashedLine(10f, 10f, 0f);

Get the X axis and Y axis from Chart?

XAxis xAxis = volumeReportChart.getXAxis();YAxis leftAxis = volumeReportChart.getAxisLeft();

we can mention the axis min and maximum values and their positions. if we want X axis position on the top, we write the below line.

XAxis.XAxisPosition position = XAxis.XAxisPosition.BOTTOM;
xAxis.setPosition(position);

Description

If you see Week text in the above chart, able to achieve it with below lines of code, Call it as description.

volumeReportChart.getDescription().setEnabled(true);
Description description = new Description();

description.setText("Week");
description.setTextSize(15f);

We can draw multiple limit lines to show chart between those specific boundaries.

Formatting the Axis labels

— — — — — — — — — — — — — — — — — — — — — — — — — — — — — — —

For example, how can we format the X axis labels (Month and date as in above picture)

ValueFormatter is the class available within this library to format the labels and other things associated with the graph.

X Axis Label

public class ClaimsXAxisValueFormatter extends ValueFormatter {

List<String> datesList;

public ClaimsXAxisValueFormatter(List<String> arrayOfDates) {
this.datesList = arrayOfDates;
}


@Override
public String getAxisLabel(float value, AxisBase axis) {
/*
Depends on the position number on the X axis, we need to display the label, Here, this is the logic to convert the float value to integer so that I can get the value from array based on that integer and can convert it to the required value here, month and date as value. This is required for my data to show properly, you can customize according to your needs.
*/
Integer position = Math.round(value);
SimpleDateFormat sdf = new SimpleDateFormat("MMM dd");

if (value > 1 && value < 2) {
position = 0;
} else if (value > 2 && value < 3) {
position = 1;
} else if (value > 3 && value < 4) {
position = 2;
} else if (value > 4 && value <= 5) {
position = 3;
}
if (position < datesList.size())
return sdf.format(new Date((Utils.getDateInMilliSeconds(datesList.get(position), "yyyy-MM-dd"))));
return "";
}
}

Here’s the method to get the date in milli seconds from string format.

Utils.java

public static long getDateInMilliSeconds(String givenDateString, String format) {
String DATE_TIME_FORMAT = format;
SimpleDateFormat sdf = new SimpleDateFormat(DATE_TIME_FORMAT, Locale.US);
long timeInMilliseconds = 1;
try {
Date mDate = sdf.parse(givenDateString);
timeInMilliseconds = mDate.getTime();
} catch (ParseException e) {
e.printStackTrace();
}
return timeInMilliseconds;
}

For example,

getDateInMilliSeconds("2020-05-25", "yyyy-MM-dd");

Y Axis Label

public class ClaimsYAxisValueFormatter extends ValueFormatter {

@Override
public String getAxisLabel(float value, AxisBase axis) {
return value + "k";
}
}

Attach these 2 labels to the chart using below lines of code.

xAxis.setValueFormatter(new ClaimsXAxisValueFormatter(dates));
leftAxis.setValueFormatter(new ClaimsYAxisValueFormatter());

All together,

Need to invoke this method, after we have the data to display.

public void renderData(List<String> dates, List<Double> allAmounts) {

final ArrayList<String> xAxisLabel = new ArrayList<>();
xAxisLabel.add("1");
xAxisLabel.add("7");
xAxisLabel.add("14");
xAxisLabel.add("21");
xAxisLabel.add("28");
xAxisLabel.add("30");

XAxis xAxis = volumeReportChart.getXAxis();
XAxis.XAxisPosition position = XAxis.XAxisPosition.BOTTOM;
xAxis.setPosition(position);
xAxis.enableGridDashedLine(2f, 7f, 0f);
xAxis.setAxisMaximum(5f);
xAxis.setAxisMinimum(0f);
xAxis.setLabelCount(6, true);
xAxis.setGranularityEnabled(true);
xAxis.setGranularity(7f);
xAxis.setLabelRotationAngle(315f);

xAxis.setValueFormatter(new ClaimsXAxisValueFormatter(dates));

xAxis.setCenterAxisLabels(true);


xAxis.setDrawLimitLinesBehindData(true);



LimitLine ll1 = new LimitLine(Float.parseFloat(UISetters.getDateInNumber()), UISetters.getDateInNumber());
ll1.setLineColor(getResources().getColor(R.color.greyish_brown));
ll1.setLineWidth(4f);
ll1.enableDashedLine(10f, 10f, 0f);
ll1.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_BOTTOM);
ll1.setTextSize(10f);

LimitLine ll2 = new LimitLine(35f, "");
ll2.setLineWidth(4f);
ll2.enableDashedLine(10f, 10f, 0f);
ll2.setLabelPosition(LimitLine.LimitLabelPosition.RIGHT_BOTTOM);
ll2.setTextSize(10f);
ll2.setLineColor(Color.parseColor("#FFFFFF"));

xAxis.removeAllLimitLines();
xAxis.addLimitLine(ll1);
xAxis.addLimitLine(ll2);


YAxis leftAxis = volumeReportChart.getAxisLeft();
leftAxis.removeAllLimitLines();
//leftAxis.addLimitLine(ll1);
//leftAxis.addLimitLine(ll2);

leftAxis.setAxisMaximum(findMaximumValueInList(allAmounts).floatValue() + 100f);
leftAxis.setAxisMinimum(0f);
leftAxis.enableGridDashedLine(10f, 10f, 0f);
leftAxis.setDrawZeroLine(false);
leftAxis.setDrawLimitLinesBehindData(false);
//XAxis xAxis = mBarChart.getXAxis();
leftAxis.setValueFormatter(new ClaimsYAxisValueFormatter());

volumeReportChart.getDescription().setEnabled(true);
Description description = new Description();
// description.setText(UISetters.getFullMonthName());//commented for weekly reporting
description.setText("Week");
description.setTextSize(15f);
volumeReportChart.getDescription().setPosition(0f, 0f);
volumeReportChart.setDescription(description);
volumeReportChart.getAxisRight().setEnabled(false);

//setData()-- allAmounts is data to display;
setDataForWeeksWise(allAmounts);

}

Entry: It is the data point on the chart (xAxis,yAxis)

Add all these data points to the chart by adding it to the LinedataSet and draw line chart by combining all those data points. And changing the line chart color, data point style, color etc.

private void setDataForWeeksWise(List<Double> amounts) {

ArrayList<Entry> values = new ArrayList<>();
values.add(new Entry(1, amounts.get(0).floatValue()));
values.add(new Entry(2, amounts.get(1).floatValue()));
values.add(new Entry(3, amounts.get(2).floatValue()));
values.add(new Entry(4, amounts.get(3).floatValue()));


LineDataSet set1;
if (volumeReportChart.getData() != null &&
volumeReportChart.getData().getDataSetCount() > 0) {
set1 = (LineDataSet) volumeReportChart.getData().getDataSetByIndex(0);
set1.setValues(values);
volumeReportChart.getData().notifyDataChanged();
volumeReportChart.notifyDataSetChanged();
} else {
set1 = new LineDataSet(values, "Total volume");
set1.setDrawCircles(true);
set1.enableDashedLine(10f, 0f, 0f);
set1.enableDashedHighlightLine(10f, 0f, 0f);
set1.setColor(getResources().getColor(R.color.toolBarColor));
set1.setCircleColor(getResources().getColor(R.color.toolBarColor));
set1.setLineWidth(2f);//line size
set1.setCircleRadius(5f);
set1.setDrawCircleHole(true);
set1.setValueTextSize(10f);
set1.setDrawFilled(true);
set1.setFormLineWidth(5f);
set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
set1.setFormSize(5.f);

if (Utils.getSDKInt() >= 18) {
// Drawable drawable = ContextCompat.getDrawable(this, R.drawable.blue_bg);
// set1.setFillDrawable(drawable);
set1.setFillColor(Color.WHITE);

} else {
set1.setFillColor(Color.WHITE);
}
set1.setDrawValues(true);
ArrayList<ILineDataSet> dataSets = new ArrayList<>();
dataSets.add(set1);
LineData data = new LineData(dataSets);

volumeReportChart.setData(data);
}
}

We can implement other charts like BarChart, Multiple chart together using this library.

Please follow documentation for more functions and information. Ping me here if you need Code base for this project.

Thanks.

--

--