Day 25 : Eaze Graph

Day 25 : Eaze Graph Cover Image

สวัสดีครับ บทความนี้เป็นบทความที่ 25 แล้วนะครับ ที่ผมจะมาเขียน ในซีรีย์ Learn 30 Android Libraries in 30 days

สำหรับบทความทั้งหมด อ่านได้จากด้านล่างครับ

สำหรับวันนี้ขอนำเสนอเรื่อง EazeGraph ตัวนี้เป็น Library ที่เอาไว้แสดง Graph บน Android ะครับ คล้ายๆกับ AChartEngine และ Android GraphView แต่จุดเด่นของ Library นี้คือเน้นความสวยงามครับ สำหรับ Graph แต่ละชนิดที่ใช้ได้ใน Library ก็ได้แก่

  • LineChart
  • BarChart
  • Stacked Bar Chart
  • PieChart

Installation

ขั้นตอนการติดตั้ง เปิดไฟล์ build.gradle ขึ้นมา แล้วเพิ่ม dependencies ลงไปดังนี้

dependencies {
    compile 'com.github.blackfizz:eazegraph:[email protected]'
}

กด Sync Gradle เป็นอันเรียบร้อย

Usage

การใช้งาน EazeGraph ในบทความนี้ ผมขอทำตัวอย่าง แค่ 3 ตัวอย่างนะครับ คือ PieChart, BarChart และ LineChart ส่วน Stacked Bar Chart มันก็คล้ายๆกับ BarChart ก็เลยไม่ทำ ไปอ่านเพิ่มเติมใน Docs ของมันเลยครับ

Pie Chart

การสร้าง PieChart จำเป็นต้องมีคลาส ดังนีครับ

  • PieChart : เป็น Container เอาไว้เก็บข้อมูลสำหรับแสดง Chart
  • PieModel : เป็นก้อน Slice ของ Pie 1 PieModel คือ Pie 1 ชิ้น สร้างได้โดย new PieChart("name", value, color)parameter คือชื่อ ค่าที่ต้องการ และสี (เป็น int เช่น 0xffff0000 หรือ `Color.parseColor(“#ff0000”))

ตัวอย่างเลเอาท์ XML ของ Pie Chart

 <org.eazegraph.lib.charts.PieChart
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/piechart"
    android:layout_width="match_parent"
    android:layout_height="300dp"
    android:padding="8dp"
    app:egLegendTextSize="18sp"
    app:egUsePieRotation="true"
    app:egValueTextSize="36sp"/>

วิธีการเรียกใช้งานจากคลาส Java

PieChart pieChart = (PieChart) findViewById(R.id.piechart);
pieChart.addPieSlice(new PieModel("Name", 100, Color.parseColor("#ff0000")));

Bar Chart

การสร้าง BarChart จำเป็นต้องมีคลาสดังนี้

  • BarChart : เป็น Container เอาไว้เก็บข้อมูลและแสดงผลแบบ Bar Chart
  • BarModel : เป็นชนิดข้อมูลแบบ Bar 1 BarModel คือข้อมูล 1 แท่ง สร้างได้โดย new BarModel("name", value, color) parameter เหมือนกับการสร้าง PieModel

ตัวอย่างเลเอาท์ XML ของ Bar Chart คือ

<org.eazegraph.lib.charts.BarChart
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/barchart"
    android:layout_width="match_parent"
    android:layout_height="256dp"
    android:padding="10dp"
    app:egFixedBarWidth="true"
    app:egBarWidth="20dp"
    app:egLegendHeight="40dp"/>

วิธีการเรียกใช้งานจากคลาส Java คือ

BarChart barChart = (BarChart) findViewById(R.id.barchart);
barChart.addBar(new BarModel("MyBarChart1", 10.5f, 0xff444444));

Line Chart

การสร้าง LineChart ต้องใช้คลาสดังนี้

  • ValueLineChart : เป็น Container เอาไว้เก็บข้อมูล และแสดง Line Chart
  • ValueLineSeries : เป็นเหมือนกลุ่มข้อมูล คล้ายๆกับ Array ของข้อมูล
  • ValueLinePoint : เป็นข้อมูลแต่ละจุด เช่น แกน x = 1, x = 2, x = 3 มีค่า 2, 3, 4 ตามลำดับ วิธีการสร้างก็คือ new ValueLinePoint(name, value) parameter คือ ชื่อ และ ค่าที่ต้องการ

ตัวอย่างไฟล์เลเอาท์ XML ของ LineChart คือ

<org.eazegraph.lib.charts.ValueLineChart
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:id="@+id/cubiclinechart"
    android:layout_width="match_parent"
    android:layout_height="200dp"
    app:egUseCubic="true"
    app:egUseOverlapFill="true"
    app:egCurveSmoothness="0.4"
    app:egIndicatorColor="#FE6DA8"
    app:egLegendHeight="40dp"
    app:egShowStandardValue="true"/>

วิธีการเรียกใช้งานจากคลาส Java คือ

ValueLineChart lineChart = (ValueLineChart) findViewById(R.id.linechart);
ValueLineSeries series = new ValueLineSeries();
series.setColor(0xffff0000);

series.addPoint(new ValueLinePoint("Red", 24.4f));
series.addPoint(new ValueLinePoint("Green", 11.3f));
series.addPoint(new ValueLinePoint("Blue", 18.6f));

lineChart.addSeries(series);

เมื่อพอรู้รายละเอียดการใช้งานคร่าวๆแล้ว มาลองสร้างโปรเจ็คกันดูเลยครับ (หากใครต้องการรายละเอียดของ Chart เพิ่มเติม อ่าน Docs ประกอบนะครับ)

Create Project

ตัวโปรเจ็คนี้ ผมจะทำการสร้างโดยใช้ ViewPager จากนั้นก็แสดง Fragment แต่ละอย่าง แบ่งเป็น PieChartFragment, BarChartFragment และ LineChartFragment นะครับ สำหรับใครที่ไม่รู้วิธีการสร้าง ViewPager อ่านได้จากบทความนี้ประกอบครับ สอนการใช้งาน ViewPager

เริ่มแรกผมทำการสร้าง เลเอาท์หลักขึ้นมาก่อน ผมตั้งชื่อว่า activity_eazegraph.xml ภายในมีแค่ ViewPager อันเดียว ดังนี้

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <android.support.v4.view.ViewPager
        android:id="@+id/pager"
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="match_parent"/>

</LinearLayout>

จากนั้นสร้างคลาส Activity หลักขึ้นมา ชื่อว่า EazeGraphActivity.java ทำการ binding ViewPager จากไฟล์ xml

public class EazeGraphActivity extends ActionBarActivity {

    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_eazegraph);
        mViewPager = (ViewPager) findViewById(R.id.pager);
    }
}

ต่อมาสร้าง Adapter ขึ้นมาโดย extends FragmentStatePagerAdapter เพื่อใช้เปลี่ยน Fragment เวลาเราเลื่อน ViewPager ตั้งชื่อคลาสว่า MyPagerAdapter อยู่ภายในคลาส EazeGraphActivity ดังนี้

package com.devahoy.learn30androidlibraries.day25;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentStatePagerAdapter;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.ActionBarActivity;

import com.devahoy.learn30androidlibraries.R;

public class EazeGraphActivity extends ActionBarActivity {

    private ViewPager mViewPager;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_eazegraph);
        mViewPager = (ViewPager) findViewById(R.id.pager);

        PagerAdapter adapter = new MyPagerAdapter(getSupportFragmentManager());
        mViewPager.setAdapter(adapter);
    }

    public class  MyPagerAdapter extends FragmentStatePagerAdapter {

        private final int NUM_OF_PAGE = 3;

        public MyPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int i) {
            Fragment fragment;
            switch (i) {
                case 0:
                    fragment = new PieChartFragment();
                    break;
                case 1:
                    fragment = new BarChartFragment();
                    break;
                case 2:
                    fragment = new LineChartFragment();
                    break;
                default:
                    fragment = new PieChartFragment();
            }
            return fragment;
        }

        @Override
        public int getCount() {
            return NUM_OF_PAGE;
        }
    }
}

จากด้านบนผมทำการสร้าง ViewPager ทั้งหมด 3 หน้า เมื่ออยู่ที่หน้าแรก จะทำการโหลด PieChartFragment มาแสดง หากเลื่อนไปหน้าสอง ก็จะโชว์ BarChartFragment และเลื่อนไปหน้าสุดท้าย ก็จะโชว์ LineChartFragment ส่วนในเมธอด onCreate() ก็ทำการสร้างออปเจ็ค MyPagerAdapter ขึ้นมา แล้วให้ ViewPager ทำการ setAdapter() ซะ เมื่อถึงตอนนี้ โค๊ดด้านบน error แน่นอน เพราะว่ายังไม่ได้สร้าง Fragment ซักอัน :D

ต่อมาสร้าง Fragment แต่ละอันเลย เริ่มจาก

PieChartFragment

ไฟล์เลเอาท์ xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:gravity="center"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <org.eazegraph.lib.charts.PieChart
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/piechart"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:padding="8dp"
        app:egLegendTextSize="18sp"
        app:egUsePieRotation="true"
        app:egValueTextSize="36sp"/>

</LinearLayout>

ตัวคลาส Java

package com.devahoy.learn30androidlibraries.day25;

import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.devahoy.learn30androidlibraries.R;

import org.eazegraph.lib.charts.PieChart;
import org.eazegraph.lib.communication.IOnItemFocusChangedListener;
import org.eazegraph.lib.models.PieModel;

public class PieChartFragment extends Fragment {

    private PieChart mPieChart;

    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.day25_fragment_pie_chart, container, false);
        mPieChart = (PieChart) view.findViewById(R.id.piechart);
        initData();

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        mPieChart.startAnimation();
    }

    private void initData() {
        mPieChart.addPieSlice(new PieModel("KitKat", 17.9f,
                Color.parseColor("#df5346")));
        mPieChart.addPieSlice(new PieModel("Jelly Bean", 56.5f,
                Color.parseColor("#6dd621")));
        mPieChart.addPieSlice(new PieModel("Ice Cream Sandwich", 11.4f,
                Color.parseColor("#1f3b83")));
        mPieChart.addPieSlice(new PieModel("Gingerbread", 13.5f,
                Color.parseColor("#34a394")));
        mPieChart.addPieSlice(new PieModel("Froyo", 0.7f,
                Color.parseColor("#22a7d0")));

        mPieChart.setOnItemFocusChangedListener(new IOnItemFocusChangedListener() {
            @Override
            public void onItemFocusChanged(int position) {
                // TODO: To do what you want.
            }
        });
    }
}

ด้านบนเป็นการสร้าง Pie Chart โดยใช้ข้อมูล Android Dashboard มาแสดง

BarChart

ไฟล์เลเอาท์ xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:gravity="center"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <org.eazegraph.lib.charts.BarChart
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/barchart"
        android:layout_width="match_parent"
        android:layout_height="400dp"
        android:padding="10dp"
        app:egFixedBarWidth="true"
        app:egBarWidth="20dp"
        app:egLegendHeight="40dp"/>

</LinearLayout>

ไฟล์ BarChartFragment.java

package com.devahoy.learn30androidlibraries.day25;


import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.devahoy.learn30androidlibraries.R;

import org.eazegraph.lib.charts.BarChart;
import org.eazegraph.lib.models.BarModel;

public class BarChartFragment extends Fragment {

    private BarChart mBarChart;

    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {

        View view = inflater.inflate(R.layout.day25_fragment_bar_chart, container, false);
        mBarChart = (BarChart) view.findViewById(R.id.barchart);

        initData();

        return view;
    }
    @Override
    public void onResume() {
        super.onResume();
        mBarChart.startAnimation();
    }

    private void initData() {
        mBarChart.addBar(new BarModel("2010", 89.4f, 0xff663397));
        mBarChart.addBar(new BarModel("2011", 53.0f, 0xff4183d7));
        mBarChart.addBar(new BarModel("2012", 100, 0xff19b5fe));
        mBarChart.addBar(new BarModel("2013", 42.9f, 0xff1e8bc3));
        mBarChart.addBar(new BarModel("2014", 113.8f, 0xff36d7b7));
    }
}

LineChart

ไฟล์เลเอาท์ xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:orientation="vertical"
              android:gravity="center"
              android:layout_width="match_parent"
              android:layout_height="match_parent">

    <org.eazegraph.lib.charts.ValueLineChart
        xmlns:app="http://schemas.android.com/apk/res-auto"
        android:id="@+id/linechart"
        android:layout_width="match_parent"
        android:layout_height="160dp"
        app:egUseCubic="true"
        app:egUseOverlapFill="true"
        app:egCurveSmoothness="0.4"
        app:egIndicatorColor="#ff1aa8fe"
        app:egLegendHeight="40dp"
        app:egShowStandardValue="true"/>

</LinearLayout>

ไฟล์ LineChart.java

package com.devahoy.learn30androidlibraries.day25;

import android.graphics.Color;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.devahoy.learn30androidlibraries.R;

import org.eazegraph.lib.charts.ValueLineChart;
import org.eazegraph.lib.models.ValueLinePoint;
import org.eazegraph.lib.models.ValueLineSeries;

public class LineChartFragment extends Fragment {

    private ValueLineChart mLineChart;
    @Override
    public View onCreateView(LayoutInflater inflater,
                             @Nullable ViewGroup container,
                             @Nullable Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.day25_fragment_line_chart, container, false);
        mLineChart = (ValueLineChart) view.findViewById(R.id.linechart);

        initData();

        return view;
    }

    @Override
    public void onResume() {
        super.onResume();
        mLineChart.startAnimation();
    }
    private void initData() {

        ValueLineSeries series = new ValueLineSeries();
        series.setColor(Color.parseColor("#f62459"));

        series.addPoint(new ValueLinePoint("Sun", 12.4f));
        series.addPoint(new ValueLinePoint("Mon", 23.4f));
        series.addPoint(new ValueLinePoint("Tue", 51.2f));
        series.addPoint(new ValueLinePoint("Wed", 26.6f));
        series.addPoint(new ValueLinePoint("Thu", 34.2f));
        series.addPoint(new ValueLinePoint("Fri", 13.5f));
        series.addPoint(new ValueLinePoint("Sat", 61.9f));

        mLineChart.addSeries(series);
    }
}

เมื่อลองรันโปรแกรม จะได้หน้าตาแบบนี้

PieChart BarChart LineChart

สรุป

จริงๆ หากใครเคยเขียน Graph/Chart ด้วย Library ตัวอื่น จะรู้สึกว่ามันคล้ายๆกันมาก วิธีการเขียน ชนิดของกราฟ แตกต่างกันบ้างเล็กน้อย หลังจากลองใช้ตัวนี้ก็รู้สึกว่า หน้าตามันสวยดี แถมมี Animation ด้วย จริงๆ AChartEngine ก็ทำได้นะ แต่ต้องปรับแต่งนานสมควร สำหรับใครที่อยากให้กราฟมันหน้าตาสวยงาม ก็ลอง EazeGraph ดูได้ครับ

สุดท้าย Source Code เหมือนเดิม จริงๆ ก็ก็อปมาแปะในบทความเกือบครบละนะ

Happy Coding :D

Chai Chai Phonbopit : Web Developer @Nimbl3 • ผู้ชายธรรมดาๆ ที่ชื่นชอบ Node.js, JavaScript และ Open Source มีงานอดิเรกเป็น Acoustic Guitar และ Football

บทความล่าสุด