web analytics

Android Code : สร้างแผนภูมิและกราฟด้วย MPAndroidChart

cover-1

บทความนี้จะบันทึกเกี่ยวกับการทำแผนภูมิและกราฟ ด้วย MPAndroidChart 3.0.0 ครับ พอได้มีโอกาสได้ใช้งานแล้วคิดว่ามันก็เจ๋งดีแหะ เลยอยากเขียนบทความเก็บไว้ โดยบทความนี้เริ่มจาก Bar chart , Pie chart ก่อน หากมีโอกาสเดี๋ยวลองตัวอื่นๆด้วย แล้วจะมาเขียนเพิ่มอีกที

 

รู้จัก MPAndroidChart

เป็นไลบรารี่เกี่ยวกับการแสดงกราฟ และแผนภูมิบน Android มีฟีเจอร์เยอะมาก ครอบคลุมการใช้งานกราฟ แผนภูมิหลายแบบ เรด้ากราฟยังมี โดยบทความนี้จะสำหรับเวอชัน 3.0.0 beta นะ ถ้าเราไป search หาใน google อาจจะเจอโค้ดของเวอชันต่ำกว่านี้ ซึ่งจะเขียนโค้ดต่างกันนิดหน่อย

รายละเอียดเพิ่มเติม
https://github.com/PhilJay/MPAndroidChart

ไลบรารี่ตัวอื่นๆ เกี่ยวกับ chart เป็นทางเลือก

 

เพิ่ม 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 เพื่อแสดงผล

1

กำหนด 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);

a1

 

กำหนด animation ทั้งแกน X , Y

chart.animateXY(3000,5000);

a2

 

สามารถกำหนดลูกเล่น animation  ได้ด้วย แบบเดียวกับ interpolation กำหนดได้ทั้งแกน X , Y
ทำให้แผนภูมิดูมีชีวิตชีวาขึ้น ลองเล่นดูครับ มีหลายตัวเลย

chart.animateXY(3000,5000, Easing.EasingOption.EaseInCubic, Easing.EasingOption.EaseInBounce);

a3

 

ความเจ๋งอีกอย่างของมันคือ สามารถ Zoom และเลื่อนได้ด้วย ลอง double tap หรือหนีบนิ้ว เพื่อ zoom

a6

ถ้าไม่อยากให้มัน 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);

 

a8

 

แผนภูมิวงกลม (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);

6

2

 

กำหนด animation

chart.animateY(3000)

a4

 

กำหนดลูกเล่น interpolator

chart.animateY(3000, Easing.EasingOption.EaseOutBounce);

a5

 

การทำ Outside Slice

คือการเอาตัวหนังสือออกมาไว้ข้างนอกตัวแผนภูมิ แล้วโยงเส้น ถ้ามีข้อมูลมากๆ โหมดนี้ก็จะเหมาะมาก เพราะประหยัดพื้นที่

ก่อนอื่นกำหนด ให้ข้อมูลอยู่ด้านนอก Slice

dataset.setXValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);
dataset.setYValuePosition(PieDataSet.ValuePosition.OUTSIDE_SLICE);

X คือ ชื่อข้อมูล
Y คือ ค่าของข้อมูล

เช่นกำหนดเฉพาะ Y ให้เป็น OUTSIDE_SLICE จะเห็นว่าชื่อข้อมูล (X) ยังอยู่ข้างในวงกลม ง่ายๆแค่นี้เลย

4

 

การกำหนดความยาวเส้นโยง

เส้นที่โยงออกมา จะมีลักษณะเป็นแบ่งเป็น 2 เส้น คือ Part1 , Part2
สามารถกำหนดความยาวมันได้

dataset.setValueLinePart1Length(0.5f);
dataset.setValueLinePart2Length(0.5f);

3

การแสดงเปอร์เซ็น (Percent)

บางกรณีอยากแสดงค่าตัวเลขเป็น % ตัวแผนภูมิวงกลมสามารถทำได้ง่ายๆ
กำหนดให้แสดงเป็น %

chart.setUsePercentValues(true);

แต่กำหนดแค่นี้มันจะไม่แสดง เครื่องหมาย % มันจะมาเฉพาะตัวเลข
ต้องกำหนด format เพิ่มด้วยที่ dataset

dataset.setValueFormatter(new PercentFormatter());

5

 

ข้อความตรงช่องกลาง

ถ้าอยากใส่ข้อความตรงกลางแผนภูมิแค่ใช้คำสั่ง

chart.setCenterText("My Android");
chart.setCenterTextSize(20);

7

 

ความเท่อีกอย่างของ PieChart คือมันหมุนได้

a7

 

เพิ่ม 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 ที่มีให้เลือก เป็นยังไงบ้าง ใช้กับแผนภูมิทุกตัว

8

Source code

https://gist.github.com/benznest/fdb1bb796bd7b50d4097d937aa0e6cfb

 

จบแล้ว

สนุกมากบทความนี้ มีสีสันดี หากใครใช้งานพวกแผนภูมิก็ลองนึกถึงไลบรารี่ตัวนี้ดูครับ ใช้งานได้ดีทีเดียว มีฟีเจอร์เยอะ
แล้วก็ลูกเล่นเพียบจริงๆ หากมีโอกาสลองนำไปใช้งานดูนะ
หากมีคำถามหรือคำแนะนำ ช่วยคอมเม้นด้วยนะครับ

 

รายละเอียดเพิ่มเติมแบบเต็มๆ

https://github.com/PhilJay/MPAndroidChart