Android Code : สร้างแผนภูมิและกราฟด้วย MPAndroidChart
บทความนี้จะบันทึกเกี่ยวกับการทำแผนภูมิและกราฟ ด้วย MPAndroidChart 3.0.0 ครับ พอได้มีโอกาสได้ใช้งานแล้วคิดว่ามันก็เจ๋งดีแหะ เลยอยากเขียนบทความเก็บไว้ โดยบทความนี้เริ่มจาก Bar chart , Pie chart ก่อน หากมีโอกาสเดี๋ยวลองตัวอื่นๆด้วย แล้วจะมาเขียนเพิ่มอีกที
รู้จัก MPAndroidChart
เป็นไลบรารี่เกี่ยวกับการแสดงกราฟ และแผนภูมิบน Android มีฟีเจอร์เยอะมาก ครอบคลุมการใช้งานกราฟ แผนภูมิหลายแบบ เรด้ากราฟยังมี โดยบทความนี้จะสำหรับเวอชัน 3.0.0 beta นะ ถ้าเราไป search หาใน google อาจจะเจอโค้ดของเวอชันต่ำกว่านี้ ซึ่งจะเขียนโค้ดต่างกันนิดหน่อย
รายละเอียดเพิ่มเติม
https://github.com/PhilJay/MPAndroidChart
ไลบรารี่ตัวอื่นๆ เกี่ยวกับ chart เป็นทางเลือก
- Holo Graph Library
- aFreeChart
- ChartDroid
- charts4j
- aChartEngine
- ChartView
- GraphView
- AndroidPlot
- WilliamChart
- HelloCharts
- EazeGraph
เพิ่ม dependencies
เนื่องจากตัวไลบรารี่ไม่ได้อยู่บน jcenter แต่อยู่ที่ maven jitpack.io ต้องไปเพิ่ม maven ก่อน
ไปที่ build.gradle ระดับ project เพิ่มลงไปใน repositories
allprojects { repositories { .. maven { url "https://jitpack.io" } } }
จากนั้นมาที่ไฟล์ build.gradle ระดับโมดูล เพิ่มไลบรารี่ MPAndroidChart ลงไป แล้ว sync ทีนึง
(เวอชันอาจมีการเปลี่ยนแปลง)
dependencies { .. compile 'com.github.PhilJay:MPAndroidChart:v3.0.0-beta1' }
เริ่มต้น
ก่อนอื่น ขอสร้างคลาส Model สมมติว่าเป็น student
และมี method สำหรับสมมุติข้อมูลนักเรียนขึ้นมา
public class Student { float score; String name; public Student(String name,float score) { this.score = score; this.name = name; } public float getScore() { return score; } public void setScore(float score) { this.score = score; } public String getName() { return name; } public void setName(String name) { this.name = name; } public static ArrayList<Student> getSampleStudentData(int size) { ArrayList<Student> student = new ArrayList<>(); for (int i = 0; i < size; i++) { student.add(new Student("Android v"+i, (float) Math.random() * 100)); } return student; } }
แผนภูมิแท่ง (Bar Chart)
มาดูหลักการนิดนึงครับ ว่าในแผนภูมิมีส่วนใดบ้าง ทุกแผนภูมิมีโครงสร้างคล้ายกันหมด ถ้าทำตัวนึงเป็น ตัวที่เหลือก็ไม่ยากละ
Entity คือ แท่งๆ อันนึงในกราฟ หรือก็คือข้อมูล 1 ตัว
Dataset คือ เอา แต่ละแท่งมาจับเป็นกลุ่มๆ
Data คือ เอา Dataset มารวมกันจะได้กราฟทั้งหมด
จากนั้นเราจะเอา Data ไป set ให้กับ Chart เพื่อแสดงผล
กำหนด Layout
แปะ View ของ BarChart ใน layout
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.benzneststudios.mychartapplication.MainActivity"> <com.github.mikephil.charting.charts.BarChart android:id="@+id/bar_chart" android:layout_width="match_parent" android:layout_height="300dp"/> </FrameLayout>
จากนั้นก็มาเขียนใน Java
เริ่มจาก findViewById มาเก็บในตัวแปร
BarChart chart = (BarChart) findViewById(R.id.bar_chart);
เตรียมข้อมูลที่จะแสดงให้พร้อม ในที่นี้ผมสุ่มขึ้นมา 30 อัน จาก Student.getSampleStudentData() ที่เตรียมไว้
final ArrayList<Student> listStudent = Student.getSampleStudentData(30);
นำข้อมูลใส่ใน Entity
Entity ใน BarChart คือคลาส BarEntry
สร้าง ArrayList<BarEntry> ขึ้นมาเพื่อเก็บข้อมูลนักเรียน และใส่ข้อมูล ลงไปใน entry แต่ละตัว
final ArrayList<BarEntry> entries = new ArrayList<>(); int index = 0; for (Student student : listStudent) { entries.add(new BarEntry(index, student.getScore())); index++; }
นำ Entity ใส่ใน Dataset
Dataset ใน BarChart คือคลาส BarDataSet
ให้เอา entity ที่เราใส่ข้อมูลไว้ในเก็บใน BarDataSet
เราสามารถ set พวกสีของแท่ง แล้วก็ขนาดตัวหนังสือได้ด้วย
BarDataSet dataset = new BarDataSet(entries, "#"); dataset.setValueTextSize(8); dataset.setColors(ColorTemplate.COLORFUL_COLORS); // set the color
นำ Dataset ใส่ Data
Data ของ Barchart คือคลาส BarData
พอได้ dataset แล้ว ก็นำมาใส่ใน BarData
เราสามารถใส่ dataset ได้หลายตัว แล้วแต่การ add ลงใน List แต่ในกรณีนี้มีตัวเดียว
ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>(); dataSets.add(dataset); BarData data = new BarData(dataSets);
นำ Data ใส่ใน Chart เพื่อแสดงผล
ขั้นตอนสุดท้ายของ การกำหนดข้อมูล คือใส่ data ลงใน chart ด้วย .setData(data)
chart.setData(data); // set data on chart.
กำหนดให้ตัวหนังสือที่ระบุชื่อ แสดงแค่ข้างล่าง และเอียง 80 องศา
chart.getXAxis().setPosition(XAxis.XAxisPosition.BOTTOM); chart.getXAxis().setLabelRotationAngle(80);
กำหนดชื่อบนแกน X อันนี้สำคัญนะ
final XAxis xAxis = chart.getXAxis(); xAxis.setTextSize(12); xAxis.setCenterAxisLabels(true); xAxis.setValueFormatter(new AxisValueFormatter() { @Override public String getFormattedValue(float value, AxisBase axis) { Log.d("benznest", "value = " + value); if (value < 0 || value >= listStudent.size()) { return ""; } return listStudent.get((int) value).getName(); } @Override public int getDecimalDigits() { return 0; } });
กำหนดให้ตัวเลขด้านขวาไม่ต้องแสดง
YAxis RightAxis = chart.getAxisRight(); RightAxis.setEnabled(false);
สามารถกำหนด animation ได้ด้วย ลองกำหนดเฉพาะ แกน Y หรือให้มันพุ่งขึ้นมาในแนวตั้ง
ลองกำหนด 3 วินาทีละกัน
chart.animateY(3000);
กำหนด animation ทั้งแกน X , Y
chart.animateXY(3000,5000);
สามารถกำหนดลูกเล่น animation ได้ด้วย แบบเดียวกับ interpolation กำหนดได้ทั้งแกน X , Y
ทำให้แผนภูมิดูมีชีวิตชีวาขึ้น ลองเล่นดูครับ มีหลายตัวเลย
chart.animateXY(3000,5000, Easing.EasingOption.EaseInCubic, Easing.EasingOption.EaseInBounce);
ความเจ๋งอีกอย่างของมันคือ สามารถ Zoom และเลื่อนได้ด้วย ลอง double tap หรือหนีบนิ้ว เพื่อ zoom
ถ้าไม่อยากให้มัน Zoom ได้ก็ปรับได้ที่
chart.setDoubleTapToZoomEnabled(false); chart.setPinchZoom(false);
แผนภูมิแท่งแนวนอน
การใช้งานเหมือนกับ BarChart ทุกประการ แค่เปลี่ยนเป็น HorizontalBarChart
พวก entry , dataset , data ก็ใช้ของ BarChar แบบเดิม
activity_main.xml
<com.github.mikephil.charting.charts.HorizontalBarChart android:id="@+id/bar_chart" android:layout_width="match_parent" android:layout_height="400dp"/>
ใน java ก็ findViewById เก็บในตัวแปรของ HorizontalBarChart
HorizontalBarChart chart = (HorizontalBarChart) findViewById(R.id.bar_chart);
แผนภูมิวงกลม (Pie Chart)
แผนภูมิวงกลม เหมาะกับการแสดงข้อมูลแบบแบ่งกลุ่มไม่มาก ทำให้เห็นภาพรวมชัดเจน
หลักการการทำงานนั้นคล้ายกับ BarChart
มีพวก Entity , Dataset , Data เหมือนกันเป๊ะ
คือคลาส PieEntry , PieDataSet , PieData
กำหนด Layout
แปะ View ของ PieChart ใน layout
activity_main.xml
<?xml version="1.0" encoding="utf-8"?> <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context="com.benzneststudios.mychartapplication.MainActivity"> <com.github.mikephil.charting.charts.PieChart android:id="@+id/pie_chart" android:layout_width="match_parent" android:layout_height="300dp" android:padding="16dp"/> </FrameLayout>
จากนั้นก็มาเขียนใน Java
ให้ findViewById มาเก็บในตัวแปร ตามสเต็ปคลาสสิค
MainActivity.java
PieChart chart = (PieChart) findViewById(R.id.pie_chart);
เตรียมข้อมูลที่จะแสดงให้พร้อม เอาสัก 5-6 อัน กำลังดี
final ArrayList<Student> listStudent = Student.getSampleStudentData(5);
นำข้อมูลใส่ใน Entity
Entity ใน PieChart คือคลาส PieEntry
สร้าง ArrayList<PieEntry> ขึ้นมาเพื่อเก็บข้อมูลนักเรียน และใส่ข้อมูล ลงไปใน entry แต่ละตัว
ArrayList<PieEntry> entries = new ArrayList<>(); for (Student student : listStudent) { entries.add(new PieEntry(student.getScore(), student.getName())); }
นำ Entity ใส่ใน Dataset
Dataset ใน PieChart คือคลาส PieDataSet
ให้เอา entity ที่เราใส่ข้อมูลไว้ในเก็บใน PieDataSet
PieDataSet dataset = new PieDataSet(entries, "Student"); dataset.setSelectionShift(10); dataset.setValueTextSize(14); dataset.setColors(ColorTemplate.MATERIAL_COLORS); // set the color
การกำหนด selectionShift คือ ขนาดของ Pie เมื่อถูกเลือก
นำ Dataset ใส่ Data
Data ของ Piechart คือคลาส PieData
พอได้ dataset แล้ว ก็นำมาใส่ใน PieData
PieData data = new PieData(dataset);
นำ Data ใส่ใน Chart เพื่อแสดงผล
ใส่ data ลงใน chart ด้วย .setData(data)
chart.setData(data);
สามารถกำหนดให้มีช่องว่างตรงกลางได้ มันจะออกมาคล้ายๆ Donut (แล้วแต่ชอบเลย)
กำหนดให้มีพื้นที่ใสๆ 40 และมันจะถูกพื้นที่ว่างลบออก ดังนั้นพื้นที่ใสจริงๆคือ 40-30 = 10
chart.setHoleRadius(30); chart.setTransparentCircleRadius(40);
กำหนด animation
chart.animateY(3000)
กำหนดลูกเล่น interpolator
chart.animateY(3000, Easing.EasingOption.EaseOutBounce);
การทำ Outside Slice
คือการเอาตัวหนังสือออกมาไว้ข้างนอกตัวแผนภูมิ แล้วโยงเส้น ถ้ามีข้อมูลมากๆ โหมดนี้ก็จะเหมาะมาก เพราะประหยัดพื้นที่
ก่อนอื่นกำหนด ให้ข้อมูลอยู่ด้านนอก Slice
dataset.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE); dataset.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
X คือ ชื่อข้อมูล
Y คือ ค่าของข้อมูล
เช่นกำหนดเฉพาะ Y ให้เป็น OUTSIDE_SLICE จะเห็นว่าชื่อข้อมูล (X) ยังอยู่ข้างในวงกลม ง่ายๆแค่นี้เลย
การกำหนดความยาวเส้นโยง
เส้นที่โยงออกมา จะมีลักษณะเป็นแบ่งเป็น 2 เส้น คือ Part1 , Part2
สามารถกำหนดความยาวมันได้
dataset.setValueLinePart1Length(0.5f); dataset.setValueLinePart2Length(0.5f);
การแสดงเปอร์เซ็น (Percent)
บางกรณีอยากแสดงค่าตัวเลขเป็น % ตัวแผนภูมิวงกลมสามารถทำได้ง่ายๆ
กำหนดให้แสดงเป็น %
chart.setUsePercentValues(true);
แต่กำหนดแค่นี้มันจะไม่แสดง เครื่องหมาย % มันจะมาเฉพาะตัวเลข
ต้องกำหนด format เพิ่มด้วยที่ dataset
dataset.setValueFormatter(new PercentFormatter());
ข้อความตรงช่องกลาง
ถ้าอยากใส่ข้อความตรงกลางแผนภูมิแค่ใช้คำสั่ง
chart.setCenterText("My Android"); chart.setCenterTextSize(20);
ความเท่อีกอย่างของ PieChart คือมันหมุนได้
เพิ่ม event เมื่อเลือกข้อมูล
สามารถกำหนดได้ว่า กดเลือกข้อมูลบนกราฟแล้วให้ทำอะไร
เช่นทำ กราฟซ้อนในกราฟอีกที เป็นแผนภูมิย่อยอีกที
chart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() { @Override public void onValueSelected(Entry e, Highlight h) { // when select data. } @Override public void onNothingSelected() { } });
Color Themplate
ที่ dataset สามารถ set พวกสีได้จาก template หรืออยากกำหนดสีเองก็ โยน List<int> เข้าไปก็ได้เช่นกัน
dataset.setColors(ColorTemplate.VORDIPLOM_COLORS); // set the color
มาดูว่าแต่ละ template ที่มีให้เลือก เป็นยังไงบ้าง ใช้กับแผนภูมิทุกตัว
Source code
https://gist.github.com/benznest/fdb1bb796bd7b50d4097d937aa0e6cfb
จบแล้ว
สนุกมากบทความนี้ มีสีสันดี หากใครใช้งานพวกแผนภูมิก็ลองนึกถึงไลบรารี่ตัวนี้ดูครับ ใช้งานได้ดีทีเดียว มีฟีเจอร์เยอะ
แล้วก็ลูกเล่นเพียบจริงๆ หากมีโอกาสลองนำไปใช้งานดูนะ
หากมีคำถามหรือคำแนะนำ ช่วยคอมเม้นด้วยนะครับ
รายละเอียดเพิ่มเติมแบบเต็มๆ
https://github.com/PhilJay/MPAndroidChart