Computer >> บทช่วยสอนคอมพิวเตอร์ >  >> การเขียนโปรแกรม >> Android

วิธีใช้ Line Chart ใน Android

สร้าง Line Chart (กราฟเส้น) ด้วย MPAndroidChart

Line Chart เป็นกราฟพื้นฐานที่นิยมมากที่สุด ใช้แสดง Trend/แนวโน้มของข้อมูลตามเวลาหรือลำดับ บทความนี้สาธิตการสร้าง Line Chart ครบถ้วน พร้อมการปรับแต่งสี จุด ขีดกริด และแอนิเมชัน

ขั้นตอนที่ 1: สร้างโปรเจกต์และเพิ่ม Dependency

Module build.gradle:

dependencies {
    implementation 'com.github.PhilJay:MPAndroidChart:v3.1.0'
}

Project build.gradle: เพิ่ม maven { url 'https://jitpack.io' }

ขั้นตอนที่ 2: Layout - activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="https://schemas.android.com/apk/res/android"
    xmlns:app="https://schemas.android.com/apk/res-auto"
    xmlns:tools="https://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <com.github.mikephil.charting.charts.LineChart
        android:id="@+id/lineChart"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="16dp" />

</androidx.constraintlayout.widget.ConstraintLayout>

ขั้นตอนที่ 3: MainActivity.java - Line Chart พื้นฐาน

package com.example.linechartdemo;

import android.graphics.Color;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private LineChart lineChart;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        lineChart = findViewById(R.id.lineChart);
        setupLineChart();
    }

    private void setupLineChart() {
        // 1. ข้อมูล Series 1
        List<Entry> entries1 = new ArrayList<>();
        entries1.add(new Entry(0, 4f));
        entries1.add(new Entry(1, 8f));
        entries1.add(new Entry(2, 6f));
        entries1.add(new Entry(3, 12f));
        entries1.add(new Entry(4, 18f));
        entries1.add(new Entry(5, 9f));
        entries1.add(new Entry(6, 15f));
        entries1.add(new Entry(7, 20f));
        entries1.add(new Entry(8, 14f));
        entries1.add(new Entry(9, 22f));

        // 2. ข้อมูล Series 2 (เปรียบเทียบ)
        List<Entry> entries2 = new ArrayList<>();
        entries2.add(new Entry(0, 2f));
        entries2.add(new Entry(1, 5f));
        entries2.add(new Entry(2, 7f));
        entries2.add(new Entry(3, 8f));
        entries2.add(new Entry(4, 10f));
        entries2.add(new Entry(5, 12f));
        entries2.add(new Entry(6, 14f));
        entries2.add(new Entry(7, 16f));
        entries2.add(new Entry(8, 18f));
        entries2.add(new Entry(9, 19f));

        // 3. สร้าง DataSet
        LineDataSet dataSet1 = new LineDataSet(entries1, "รายได้");
        dataSet1.setColor(ColorTemplate.MATERIAL_COLORS[0]);
        dataSet1.setCircleColor(ColorTemplate.MATERIAL_COLORS[0]);
        dataSet1.setLineWidth(2.5f);
        dataSet1.setCircleRadius(4f);
        dataSet1.setDrawCircleHole(true);
        dataSet1.setCircleHoleRadius(2f);
        dataSet1.setValueTextColor(Color.BLACK);
        dataSet1.setValueTextSize(10f);
        dataSet1.setDrawValues(true);
        dataSet1.setMode(LineDataSet.Mode.CUBIC_BEZIER); // โค้งมน (Smooth)
        dataSet1.setCubicIntensity(0.2f);
        dataSet1.setFillColor(ColorTemplate.MATERIAL_COLORS[0]);
        dataSet1.setDrawFilled(true);
        dataSet1.setFillAlpha(50);

        LineDataSet dataSet2 = new LineDataSet(entries2, "ค่าใช้จ่าย");
        dataSet2.setColor(ColorTemplate.MATERIAL_COLORS[1]);
        dataSet2.setCircleColor(ColorTemplate.MATERIAL_COLORS[1]);
        dataSet2.setLineWidth(2.5f);
        dataSet2.setCircleRadius(4f);
        dataSet2.setDrawCircleHole(true);
        dataSet2.setCircleHoleRadius(2f);
        dataSet2.setValueTextColor(Color.BLACK);
        dataSet2.setValueTextSize(10f);
        dataSet2.setDrawValues(true);
        dataSet2.setMode(LineDataSet.Mode.CUBIC_BEZIER);
        dataSet2.setFillColor(ColorTemplate.MATERIAL_COLORS[1]);
        dataSet2.setDrawFilled(true);
        dataSet2.setFillAlpha(50);

        // 4. รวม Data
        List<ILineDataSet> dataSets = new ArrayList<>();
        dataSets.add(dataSet1);
        dataSets.add(dataSet2);
        LineData lineData = new LineData(dataSets);
        lineChart.setData(lineData);

        // 5. ปรับแต่ง Chart
        customizeLineChart();
    }

    private void customizeLineChart() {
        // Description
        lineChart.getDescription().setEnabled(false);

        // Touch
        lineChart.setTouchEnabled(true);
        lineChart.setDragEnabled(true);
        lineChart.setScaleEnabled(true);
        lineChart.setPinchZoom(true);
        lineChart.setHighlightPerDragEnabled(true);

        // Background
        lineChart.setDrawGridBackground(false);
        lineChart.setBackgroundColor(Color.WHITE);

        // X Axis (Bottom)
        com.github.mikephil.charting.components.XAxis xAxis = lineChart.getXAxis();
        xAxis.setPosition(com.github.mikephil.charting.components.XAxis.XAxisPosition.BOTTOM);
        xAxis.setGranularity(1f);
        xAxis.setLabelCount(10);
        xAxis.setValueFormatter((value, axis) -> {
            String[] months = {"ม.ค.", "ก.พ.", "มี.ค.", "เม.ย.", "พ.ค.", "มิ.ย.", "ก.ค.", "ส.ค.", "ก.ย.", "ต.ค."};
            int index = (int) value;
            return (index >= 0 && index < months.length) ? months[index] : "";
        });

        // Y Axis Left
        com.github.mikephil.charting.components.YAxis leftAxis = lineChart.getAxisLeft();
        leftAxis.setAxisMinimum(0f);
        leftAxis.setGranularity(5f);
        leftAxis.setLabelCount(6);
        leftAxis.setValueFormatter((value, axis) -> String.format("%,.0f", value));
        leftAxis.setDrawGridLines(true);
        leftAxis.setGridColor(Color.LTGRAY);
        leftAxis.setGridLineWidth(0.5f);

        // Y Axis Right (Disable)
        lineChart.getAxisRight().setEnabled(false);

        // Legend
        lineChart.getLegend().setEnabled(true);
        lineChart.getLegend().setVerticalAlignment(com.github.mikephil.charting.components.Legend.LegendVerticalAlignment.TOP);
        lineChart.getLegend().setHorizontalAlignment(com.github.mikephil.charting.components.Legend.LegendHorizontalAlignment.RIGHT);
        lineChart.getLegend().setOrientation(com.github.mikephil.charting.components.Legend.LegendOrientation.VERTICAL);
        lineChart.getLegend().setDrawInside(false);

        // Animation
        lineChart.animateX(1500);

        // Marker (Tooltip เมื่อกด)
        MyMarkerView marker = new MyMarkerView(this, R.layout.custom_marker_view);
        marker.setChartView(lineChart);
        lineChart.setMarker(marker);

        lineChart.invalidate();
    }
}

Custom Marker View (Tooltip) - res/layout/custom_marker_view.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    android:background="@drawable/marker_bg"
    android:padding="8dp">

    <TextView
        android:id="@+id/tvMarkerLabel"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF"
        android:textSize="12sp"
        android:textStyle="bold" />

    <TextView
        android:id="@+id/tvMarkerValue"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:textColor="#FFFFFF"
        android:textSize="14sp" />

</LinearLayout>
// res/drawable/marker_bg.xml
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="https://schemas.android.com/apk/res/android">
    <solid android:color="#333333" />
    <corners android:radius="4dp" />
</shape>
// MyMarkerView.java
public class MyMarkerView extends MarkerView {
    private TextView tvLabel, tvValue;

    public MyMarkerView(Context context, int layoutResource) {
        super(context, layoutResource);
        tvLabel = findViewById(R.id.tvMarkerLabel);
        tvValue = findViewById(R.id.tvMarkerValue);
    }

    @Override
    public void refreshContent(Entry e, Highlight highlight) {
        if (e instanceof Entry) {
            tvLabel.setText("เดือน " + (int)(e.getX() + 1));
            tvValue.setText(String.format("%,.0f บาท", e.getY()));
        }
        super.refreshContent(e, highlight);
    }

    @Override
    public MPPointF getOffset() {
        return new MPPointF(-(getWidth() / 2f), -getHeight() - 10);
    }
}

การตั้งค่าขั้นสูง

1. Limit Line (เส้นเกณฑ์/เป้าหมาย)

LimitLine upperLimit = new LimitLine(20f, "เป้าหมาย 20K");
upperLimit.setLineWidth(2f);
upperLimit.setLineColor(Color.RED);
upperLimit.setTextSize(10f);
upperLimit.setTextColor(Color.RED);
upperLimit.enableDashedLine(10f, 10f, 0f);
lineChart.getAxisLeft().addLimitLine(upperLimit);

2. Gradient Fill (เงารadian)

// ต้องใช้ FillDrawable
Drawable drawable = ContextCompat.getDrawable(this, R.drawable.gradient_fill);
dataSet1.setFillDrawable(drawable);

3. Multiple Y-Axes (สำหรับ Scale ต่างกัน)

// เพิ่ม YAxis ด้านขวาสำหรับ Series ที่ Scale ต่างกัน
lineChart.getAxisRight().setEnabled(true);
dataSet2.setAxisDependency(YAxis.AxisDependency.RIGHT);

สรุป

Line Chart ของ MPAndroidChart ใช้ Entry(x, y) และ LineDataSet รองรับฟีเจอร์ครบ: Smooth Curve (CUBIC_BEZIER), Fill Area, Limit Lines, Custom Markers, Multiple Axes, Animations เหมาะสำหรับ Dashboard, Finance, Analytics Apps