Selamat pagi semua, kali ini admin ingin mengulas tentang library chart atau library untuk membuat chart atau grafik pada Android. Yap, siapa yang tidak kenal tentang library yang satu ini yaitu MPAndroidChart.
MPAndroidChart merupakan library yang dibangun oleh mas Philipp Jahoda aka Philjay beserta timnya. Library ini bersifat gratis dan kalian bisa download langsung source code nya dari situs GitHub atau dapat menggunakannya langsung pada Android Studio dengan cara menambahkan kode pada berikut pada file
build.gradle
pada project Android kalian.implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
Jangan lupa versi yang digunakan kalau bisa versi terbaru. Untuk saat ini yang sedang admin gunakan adalah Versi 3.1.0 adalah versi terbaru.
Library ini memiliki beberapa jenis chart yang dapat kalian gunakan diantaranya LineChart (Grafik garis), BarChart (Grafik batang), PieChart (Grafik donat), ScatterChart, CandleStickChart, dan RadarChart yang kesemuanya gratis dan dibawah lisensi Apache License, Version 2.0.
Dalam tutorial ini, beberapa chart yang jarang penggunaannya seperti Scatter Chart, Candle Stick Chart, dan Radar Chart tidak akan dibahas lebih serius. Hanya beberapa chart saja seperti Line Chart(Grafik garis), dan Bar Chart (Grafik batang) yang akan dibahas penggunaannya.
Installasi MPAndroidChart pada Android Studio
Untuk menggunakannya, seperti dijelaskan diatas, kita hanya perlu menambahkan kode impelementasi dependencies dan repositories pada file Gradle. Kode lengkapnya seperti berikut :dependencies { implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0' } repositories { maven { url 'https://jitpack.io' } }
Tunggulah beberapa saat sampai selesai ketika gradle melakukan syncing dengan server.
Perlu sedikit diketahui bahwa sebuah grafik memiliki data, data ini biasanya dibungkus dalam sebuah array yang menentukan lokasi data sebuah grafik atau chart. Di MPAndroidChart, data yang dibungkus ini dikenal juga sebagai Entry.
Contoh dari Entry misalnya data pada tanggal 19 April 2020 berisi nilai
X=20
dan Y=30
. Maka output dari entry tersebut kurang lebih [Entry, X:20, Y:30]
1. Line Chart
Line Chart atau kita mengenalnya dengan grafik garis adalah sebuah grafik yang menyajikan data dalam bentuk garis atau kurva (curve). Grafik garis digunakan untuk menggambarkan perkembangan data dari waktu ke waktu terhadap nilai sebuah objek yang diteliti.Grafik garis terdiri dari sumbu X dan sumbu Y, dimana umumnya sumbu X digunakan untuk menampilkan waktu pengamatan. Sebaliknya sumbu Y digunakan untuk menampilkan nilai atau hasil dari pengamatan.
Untuk cara penggunaannya dapat dipanggil langsung melalui layout XML pada Android Studio.
<com.github.mikephil.charting.charts.LineChart android:id="@+id/lineChart" android:minHeight="200dp" android:layout_width="match_parent" android:layout_height="wrap_content"/>
Memasukkan Data kedalam Grafik LineChart
Untuk memasukkan data ke dalam grafik, kita membutuhkan objekEntry
dengan tipe data Array yang kemudian disematkan kedalam objek LineDataSet
. Dalam contoh ini kita akan menampilkan data berikut menjadi sebuah grafik garis :[ads id="ads1"]
DATA KASUS COVID-19 1 APRIL 2020 S/D 10 APRIL 2020
Tanggal | Kasus | Sembuh | Meninggal |
---|---|---|---|
01-April-2020 | 149 | 22 | 21 |
02-April-2020 | 113 | 9 | 13 |
03-April-2020 | 196 | 22 | 11 |
04-April-2020 | 106 | 16 | 10 |
05-April-2020 | 181 | 14 | 7 |
06-April-2020 | 218 | 28 | 11 |
07-April-2020 | 247 | 12 | 12 |
08-April-2020 | 218 | 18 | 19 |
09-April-2020 | 337 | 30 | 40 |
10-April-2020 | 219 | 30 | 26 |
Dari data diatas, kita akan membuat satu persatu DataSet sehingga menjadi 3 objek dataset yang akan dibuat meliputi dataset "Kasus", "Sembuh", dan "Meninggal".
Untuk format tanggal kita akan menggunakan ValueFormatter sebagai penampil tanggal. Kita tidak dapat langsung memasukkan nilai tanggal dikarenakan format dari objek Entry itu sendiri adalah float.
val kasus = ArrayList<Entry>() kasus.add(Entry(0F, 149F)) kasus.add(Entry(1F, 113F)) kasus.add(Entry(2F, 196F)) kasus.add(Entry(3F, 106F)) kasus.add(Entry(4F, 181F)) kasus.add(Entry(5F, 218F)) kasus.add(Entry(6F, 247F)) kasus.add(Entry(7F, 218F)) kasus.add(Entry(8F, 337F)) kasus.add(Entry(9F, 219F)) val sembuh = ArrayList<Entry>() sembuh.add(Entry(0F, 22F)) sembuh.add(Entry(1F, 9F)) sembuh.add(Entry(2F, 22F)) sembuh.add(Entry(3F, 16F)) sembuh.add(Entry(4F, 14F)) sembuh.add(Entry(5F, 28F)) sembuh.add(Entry(6F, 12F)) sembuh.add(Entry(7F, 18F)) sembuh.add(Entry(8F, 30F)) sembuh.add(Entry(9F, 30F)) val meninggal = ArrayList<Entry>() meninggal.add(Entry(0F, 21F)) meninggal.add(Entry(1F, 13F)) meninggal.add(Entry(2F, 11F)) meninggal.add(Entry(3F, 10F)) meninggal.add(Entry(4F, 7F)) meninggal.add(Entry(5F, 11F)) meninggal.add(Entry(6F, 12F)) meninggal.add(Entry(7F, 19F)) meninggal.add(Entry(8F, 40F)) meninggal.add(Entry(9F, 26F)) val kasusLineDataSet = LineDataSet(kasus, "Kasus") kasusLineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER kasusLineDataSet.color = Color.BLUE kasusLineDataSet.circleRadius = 5f kasusLineDataSet.setCircleColor(Color.BLUE) val sembuhLineDataSet = LineDataSet(sembuh, "Sembuh") sembuhLineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER sembuhLineDataSet.color = Color.GREEN sembuhLineDataSet.circleRadius = 5f sembuhLineDataSet.setCircleColor(Color.GREEN) val meninggalLineDataSet = LineDataSet(meninggal, "Meninggal") meninggalLineDataSet.mode = LineDataSet.Mode.CUBIC_BEZIER meninggalLineDataSet.color = Color.RED meninggalLineDataSet.circleRadius = 5f meninggalLineDataSet.setCircleColor(Color.RED) //Setup Legend val legend = lineChart.legend legend.isEnabled = true legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP) legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER) legend.setOrientation(Legend.LegendOrientation.HORIZONTAL) legend.setDrawInside(false) lineChart.description.isEnabled = false lineChart.xAxis.position = XAxis.XAxisPosition.BOTTOM lineChart.data = LineData(kasusLineDataSet, sembuhLineDataSet, meninggalLineDataSet) lineChart.animateXY(100, 500)
Hasil akhir dari kode diatas akan menjadi seperti ini :
Formatting Tanggal Grafik dengan ValueFormatter
Kita tidak dapat langsung memasukkan nilai tanggal kedalamEntry
dikarenakan parameter X dan Y dari objek Entry itu sendiri adalah memiliki tipe data float, Untuk memasukkan nilai tanggal pada MPAndroidChart dapat menggunakan objek ValueFormatter yang telah disediakan.Agar lebih mudah dipahami, buatlah sebuah class baru dengan nama AxisDateFormatter, tujuannya agar lebih mudah menampung format data yang ingin digunakan. Berikut contohnya :
AxisDateFormatter.kt
import com.github.mikephil.charting.formatter.ValueFormatter class AxisDateFormatter(private val mValues: Array<String>) : ValueFormatter() { override fun getFormattedValue(value: Float): String { return if (value >= 0) { if (mValues.size > value.toInt()) { mValues[value.toInt()] } else "" } else { "" } } }
Contoh penggunaan AxisDateFormatter :
var date = ArrayList<String>(); date.add("01-Apr") date.add("02-Apr") date.add("03-Apr") date.add("04-Apr") date.add("05-Apr") date.add("06-Apr") date.add("07-Apr") date.add("08-Apr") date.add("09-Apr") date.add("10-Apr") val tanggal = AxisDateFormatter(date.toArray(arrayOfNulls<String>(date.size))) lineChart.xAxis?.setValueFormatter(tanggal);
Hasil akhir dari kode diatas kurang lebih menjadi seperti ini (dengan formatting tanggal pada X Axis (AxisDateFormatter)):
Membuat MarkerView
MarkerView adalah objek dari MPAndroidChart yang kegunaannya untuk menampilkan data dari Entry/item yang diklik pada grafik sehingga menampilkan sebuah popup informasi mengenai entry tersebut.Masih pada chart dan contoh yang sama, kita akan menampilkan data dari setiap item yang diklik dalam bentuk popup. Buatlah sebuah class baru dengan nama LineChartMarkerView.
LineChartMarkerView.kt
import android.content.Context import android.widget.TextView import com.github.mikephil.charting.charts.LineChart import com.github.mikephil.charting.components.IMarker import com.github.mikephil.charting.components.MarkerView import com.github.mikephil.charting.data.DataSet import com.github.mikephil.charting.data.Entry import com.github.mikephil.charting.highlight.Highlight import com.github.mikephil.charting.utils.MPPointF class LineChartMarkerView(context: Context?, private val lineChart: LineChart, layoutResource: Int, axisX: AxisDateFormatter) : MarkerView(context, layoutResource), IMarker { private val square1: TextView private val square2: TextView private val square3: TextView private val item1: TextView private val item2: TextView private val item3: TextView private val Title: TextView private val XAxis: AxisDateFormatter init { square1 = findViewById(R.id.square1) square2 = findViewById(R.id.square2) square3 = findViewById(R.id.square3) item1 = findViewById(R.id.item1) item2 = findViewById(R.id.item2) item3 = findViewById(R.id.item3) Title = findViewById(R.id.txtTitle) XAxis = axisX } override fun refreshContent( e: Entry, highlight: Highlight) { try { Title.text = XAxis.getFormattedValue(e.x).toString() square1.setBackgroundColor(lineChart.data.getDataSetByIndex(0).color) square2.setBackgroundColor(lineChart.data.getDataSetByIndex(1).color) square3.setBackgroundColor(lineChart.data.getDataSetByIndex(2).color) val val1 = lineChart.data.getDataSetByIndex(0).getEntryForXValue(e.x, Float.NaN, DataSet.Rounding.CLOSEST) as Entry val val2 = lineChart.data.getDataSetByIndex(1).getEntryForXValue(e.x, Float.NaN, DataSet.Rounding.CLOSEST) as Entry val val3 = lineChart.data.getDataSetByIndex(2).getEntryForXValue(e.x, Float.NaN, DataSet.Rounding.CLOSEST) as Entry item1.text = String.format("%,.0f", val1.y) item2.text = String.format("%,.0f", val2.y) item3.text = String.format("%,.0f", val3.y) } catch (ex: Exception) { ex.printStackTrace() } super.refreshContent(e, highlight) } private var mOffset: MPPointF? = null override fun getOffset(): MPPointF { if (mOffset == null) { mOffset = MPPointF((-(width / 2)).toFloat(), (-height).toFloat()) } return mOffset!! } }
MarkerView membutuhkan layout sebagai desain dan juga untuk penggunaan objek sesuai class yang dibuat diatas. Buatlah sebuah layout dengan nama markerview_three_item untuk desain markerview dan drawable bg_white_border untuk mempercantik desain layout markerview.
markerview_three_item.xml
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/container" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingVertical="5dp" android:paddingHorizontal="10dp" android:clickable="true" android:background="@drawable/bg_white_border" android:layout_marginBottom="10dp" android:orientation="vertical"> <TextView android:id="@+id/txtTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="Title" android:textStyle="bold" android:textColor="@android:color/black" android:singleLine="true" android:textSize="10dp" android:textAppearance="?android:attr/textAppearanceSmall" /> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/square1" android:layout_width="10dp" android:layout_height="10dp" android:textColor="@android:color/black" android:layout_gravity="center_vertical" android:background="@android:color/black" android:singleLine="true" android:layout_marginRight="2dp" android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView android:id="@+id/item1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="Item 1" android:textColor="@android:color/black" android:singleLine="true" android:textSize="10dp" android:textAppearance="?android:attr/textAppearanceSmall" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/square2" android:layout_width="10dp" android:layout_height="10dp" android:textColor="@android:color/black" android:layout_gravity="center_vertical" android:background="@android:color/black" android:singleLine="true" android:layout_marginRight="2dp" android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView android:id="@+id/item2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="Item 2" android:textColor="@android:color/black" android:singleLine="true" android:textSize="10dp" android:textAppearance="?android:attr/textAppearanceSmall" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:id="@+id/square3" android:layout_width="10dp" android:layout_height="10dp" android:textColor="@android:color/black" android:layout_gravity="center_vertical" android:background="@android:color/black" android:singleLine="true" android:layout_marginRight="2dp" android:textAppearance="?android:attr/textAppearanceSmall" /> <TextView android:id="@+id/item3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerHorizontal="true" android:text="Item 3" android:textColor="@android:color/black" android:singleLine="true" android:textSize="10dp" android:textAppearance="?android:attr/textAppearanceSmall" /> </LinearLayout> </LinearLayout>
bg_white_border.xml
<?xml version="1.0" encoding="utf-8"?> <layer-list xmlns:android="http://schemas.android.com/apk/res/android"> <item> <shape> <stroke android:dashGap="0px" android:dashWidth="0px" android:width="1dp" android:color="#ababb2" /> <solid android:color="@android:color/white"/> </shape> </item> </layer-list>
Contoh penggunaannya seperti berikut :
val marker : IMarker = LineChartMarkerView(applicationContext, lineChart, R.layout.markerview_three_item, tanggal); lineChart.marker = marker;
Sehingga tampilan akhir/output dari kode diatas menjadi seperti berikut :
[ads id="ads2"]
2. Bar Chart
Grafik selanjutnya adalah Bar Chart atau kita mengenalnya dengan grafik batang, merupakan jenis grafik yang dipakai untuk menekankan perbedaan tingkat nilai dan aspek. Grafik batang merupakan jenis grafik yang paling sederhana. Kekurangan dari grafik batang adalah data yang dapat ditampilkan atau dibandingkan relatif tidak terlalu banyak.Untuk cara penggunaannya pun sama dengan grafik LineChart, dapat dipanggil langsung melalui layout XML pada Android Studio.
<com.github.mikephil.charting.charts.BarChart android:id="@+id/lineChart" android:minHeight="200dp" android:layout_width="match_parent" android:layout_height="wrap_content"/>
Memasukkan Data kedalam Grafik BarChart
Untuk memasukkan data ke dalam grafik BarChart (grafik batang), kita membutuhkan objekBarEntry
(berbeda dengan objek LineChart) dengan tipe data Array yang kemudian disematkan kedalam objek BarDataSet
. Dalam contoh ini kita akan menampilkan data berikut menjadi sebuah grafik batang :
DATA KASUS COVID-19 1 APRIL 2020 S/D 10 APRIL 2020
Tanggal | Kasus | Sembuh | Meninggal |
---|---|---|---|
01-April-2020 | 149 | 22 | 21 |
02-April-2020 | 113 | 9 | 13 |
03-April-2020 | 196 | 22 | 11 |
04-April-2020 | 106 | 16 | 10 |
05-April-2020 | 181 | 14 | 7 |
06-April-2020 | 218 | 28 | 11 |
07-April-2020 | 247 | 12 | 12 |
08-April-2020 | 218 | 18 | 19 |
09-April-2020 | 337 | 30 | 40 |
10-April-2020 | 219 | 30 | 26 |
Dari data diatas, kita akan membuat satu persatu BarDataSet sehingga menjadi 3 objek bardataset yang akan dibuat meliputi dataset "Kasus", "Sembuh", dan "Meninggal".
val legend = barChart.legend legend.isEnabled = true legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP) legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER) legend.setOrientation(Legend.LegendOrientation.HORIZONTAL) legend.setDrawInside(false) val kasus = ArrayList<BarEntry>() kasus.add(BarEntry(0F, 149F)) kasus.add(BarEntry(1F, 113F)) kasus.add(BarEntry(2F, 196F)) kasus.add(BarEntry(3F, 106F)) kasus.add(BarEntry(4F, 181F)) kasus.add(BarEntry(5F, 218F)) kasus.add(BarEntry(6F, 247F)) kasus.add(BarEntry(7F, 218F)) kasus.add(BarEntry(8F, 337F)) kasus.add(BarEntry(9F, 219F)) val sembuh = ArrayList<BarEntry>() sembuh.add(BarEntry(0F, 22F)) sembuh.add(BarEntry(1F, 9F)) sembuh.add(BarEntry(2F, 22F)) sembuh.add(BarEntry(3F, 16F)) sembuh.add(BarEntry(4F, 14F)) sembuh.add(BarEntry(5F, 28F)) sembuh.add(BarEntry(6F, 12F)) sembuh.add(BarEntry(7F, 18F)) sembuh.add(BarEntry(8F, 30F)) sembuh.add(BarEntry(9F, 30F)) val meninggal = ArrayList<BarEntry>() meninggal.add(BarEntry(0F, 21F)) meninggal.add(BarEntry(1F, 13F)) meninggal.add(BarEntry(2F, 11F)) meninggal.add(BarEntry(3F, 10F)) meninggal.add(BarEntry(4F, 7F)) meninggal.add(BarEntry(5F, 11F)) meninggal.add(BarEntry(6F, 12F)) meninggal.add(BarEntry(7F, 19F)) meninggal.add(BarEntry(8F, 40F)) meninggal.add(BarEntry(9F, 26F)) val kasusBarDataSet = BarDataSet(kasus, "Kasus") kasusBarDataSet.color = Color.BLUE val sembuhBarDataSet = BarDataSet(sembuh, "Sembuh") sembuhBarDataSet.color = Color.GREEN val meninggalBarDataSet = BarDataSet(meninggal, "Meninggal") meninggalBarDataSet.color = Color.RED barChart.description.isEnabled = false barChart.xAxis.position = XAxis.XAxisPosition.BOTTOM barChart.data = BarData(kasusBarDataSet, sembuhBarDataSet, meninggalBarDataSet) barChart.animateXY(100, 500)
Hasil akhirnya menjadi seperti berikut :
Membuat Group pada BarChart
Secara default, barchart tidak melakukan grouping dataset. Untuk melakukan grouping, kita memerlukan sedikit konfigurasi seperti jarak grup antar bar, spasi, dan lebar bar. Perhatikan visualisasi dibawah ini :Untuk membuat group pada barchart, penggunaannya seperti berikut :
barChart.description.isEnabled = false barChart.xAxis?.position = XAxis.XAxisPosition.BOTTOM barChart.xAxis?.granularity = 1f barChart.xAxis?.setCenterAxisLabels(true) barChart.xAxis?.setDrawGridLines(true) barChart.xAxis?.spaceMin = 0f barChart.axisLeft.axisMinimum = 0f barChart.axisLeft.spaceTop = 35f barChart.axisLeft.setDrawGridLines(true) barChart.axisRight.isEnabled = false; val legend = barChart.legend legend.isEnabled = true legend.setVerticalAlignment(Legend.LegendVerticalAlignment.TOP) legend.setHorizontalAlignment(Legend.LegendHorizontalAlignment.CENTER) legend.setOrientation(Legend.LegendOrientation.HORIZONTAL) legend.setDrawInside(true) val kasus = ArrayList<BarEntry>() kasus.add(BarEntry(0F, 149F)) kasus.add(BarEntry(1F, 113F)) kasus.add(BarEntry(2F, 196F)) kasus.add(BarEntry(3F, 106F)) kasus.add(BarEntry(4F, 181F)) kasus.add(BarEntry(5F, 218F)) kasus.add(BarEntry(6F, 247F)) kasus.add(BarEntry(7F, 218F)) kasus.add(BarEntry(8F, 337F)) kasus.add(BarEntry(9F, 219F)) val sembuh = ArrayList<BarEntry>() sembuh.add(BarEntry(0F, 22F)) sembuh.add(BarEntry(1F, 9F)) sembuh.add(BarEntry(2F, 22F)) sembuh.add(BarEntry(3F, 16F)) sembuh.add(BarEntry(4F, 14F)) sembuh.add(BarEntry(5F, 28F)) sembuh.add(BarEntry(6F, 12F)) sembuh.add(BarEntry(7F, 18F)) sembuh.add(BarEntry(8F, 30F)) sembuh.add(BarEntry(9F, 30F)) val meninggal = ArrayList<BarEntry>() meninggal.add(BarEntry(0F, 21F)) meninggal.add(BarEntry(1F, 13F)) meninggal.add(BarEntry(2F, 11F)) meninggal.add(BarEntry(3F, 10F)) meninggal.add(BarEntry(4F, 7F)) meninggal.add(BarEntry(5F, 11F)) meninggal.add(BarEntry(6F, 12F)) meninggal.add(BarEntry(7F, 19F)) meninggal.add(BarEntry(8F, 40F)) meninggal.add(BarEntry(9F, 26F)) val kasusBarDataSet = BarDataSet(kasus, "Kasus") kasusBarDataSet.color = Color.BLUE val sembuhBarDataSet = BarDataSet(sembuh, "Sembuh") sembuhBarDataSet.color = Color.GREEN val meninggalBarDataSet = BarDataSet(meninggal, "Meninggal") meninggalBarDataSet.color = Color.RED val groupSpace = 0.08f val barSpace = 0.03f val barWidth = 0.27f val groupBar = BarData(kasusBarDataSet, sembuhBarDataSet, meninggalBarDataSet) groupBar.barWidth = barWidth barChart.data = groupBar barChart.groupBars(0f, groupSpace, barSpace) barChart.animateXY(100, 500)
Hasil akhirnya menjadi seperti berikut ini :
Formatting Tanggal BarChart dengan ValueFormatter
Untuk melakukan formatting tanggal kurang lebih sama dengan cara diatas.Berikut contoh penggunaannya :
var date = ArrayList<String>(); date.add("01-Apr") date.add("02-Apr") date.add("03-Apr") date.add("04-Apr") date.add("05-Apr") date.add("06-Apr") date.add("07-Apr") date.add("08-Apr") date.add("09-Apr") date.add("10-Apr") val tanggal = AxisDateFormatter(date.toArray(arrayOfNulls<String>(date.size))) barChart.xAxis?.setValueFormatter(tanggal);
Terima kasih sudah membaca dan untuk yang membutuhkan source code sebagai panduan atau sekedar pembelajaran lebih lanjut, dapat kalian download di https://drive.google.com/open?id=1ooPq8AfGid8kcvBkXetgusszgS4tmHn4
Semoga bermanfaat.
Posting Komentar