สร้าง 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