MPAndroidChartでLineChartを描く
MPAndroidChartでLineChartを描くのに苦労しましたので、サンプルコードを載せておきます。
private class GraphManager {
private LinearLayout chartLayout;
private final Context context;
public GraphManager(Context context) {
this.context = context;
}
@SuppressWarnings("ConstantConditions")
public void displayGraph(
String legend,
int dataCount,
Date[] dateValue,
boolean[] flagActual,
double[] yActualValue,
boolean[] flagActualNight,
double[] yActualValueNight,
boolean[] flagTarget,
double[] yTargetValue) {
Resources resources = getResources();
DataCenter dataCenter = new DataCenter();
View view = dataCenter.getGraphView();
LineChart lineChart = view.findViewById(R.id.chartArea);
lineChart.getAxisRight().setEnabled(false);
lineChart.getAxisLeft().setEnabled(true);
lineChart.setDrawGridBackground(true);
lineChart.setTouchEnabled(false);
lineChart.setPinchZoom(false);
lineChart.setDoubleTapToZoomEnabled(false);
lineChart.setScaleEnabled(true);
lineChart.getLegend().setEnabled(true);
lineChart.getDescription().setText("");
//X軸周り
XAxis xAxis = lineChart.getXAxis();
xAxis.setDrawLabels(true);
xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
xAxis.setDrawGridLines(true);
YAxis yAxis = lineChart.getAxisLeft();
yAxis.setLabelCount(10);
lineChart.setData(createLineChartData(
legend,
xAxis,
dataCount,
dateValue,
flagActual,
yActualValue,
flagActualNight,
yActualValueNight,
flagTarget,
yTargetValue
));
lineChart.invalidate();
}
private LineData createLineChartData(
String legend,
XAxis xAxis,
int dataCount,
Date[] dateValue,
boolean[] existFlagActual,
double[] yActualValue,
boolean[] existFlagActualNight,
double[] yActualValueNight,
boolean[] existFlagTarget,
double[] yTargetValue) {
xAxis.setValueFormatter(new XAxisValueFormatter(dateValue));
Point point = getDisplaySize(getActivity());
reverseOrderDate(dateValue);
reverseOrder(yActualValue, existFlagActual);
reverseOrder(yActualValueNight, existFlagActualNight);
reverseOrder(yTargetValue, existFlagTarget);
ArrayList<Entry> actualValues = new ArrayList<>();
for (int i=0; i<existFlagActual.length; i++) {
if (existFlagActual[i]) {
actualValues.add(new Entry((float)i, (float)yActualValue[i]));
}
}
ArrayList<Entry> actualValuesNight = new ArrayList<>();
for (int i=0; i<existFlagActualNight.length; i++) {
if (existFlagActualNight[i]) {
actualValuesNight.add(new Entry((float)i, (float)yActualValueNight[i]));
}
}
ArrayList<Entry> targetValues = new ArrayList<>();
for (int i=0; i<existFlagTarget.length; i++) {
if (existFlagTarget[i]) {
targetValues.add(new Entry((float)i, (float)yTargetValue[i]));
}
}
List<ILineDataSet> dataSets = new ArrayList<>();
LineDataSet actualTargetDataSet = new LineDataSet(targetValues, legend + "(" + getString(R.string.graph_target) + ")");
actualTargetDataSet.setColor(Color.rgb(180, 0, 180));
actualTargetDataSet.setCircleColor(Color.rgb(180, 0, 180));
actualTargetDataSet.setLineWidth(2f);
actualTargetDataSet.setDrawValues(false);
dataSets.add(actualTargetDataSet);
LineDataSet actualDataSet = new LineDataSet(actualValues, legend + "(" + getString(R.string.graph_legend_morning) + ")");
actualDataSet.setColor(Color.rgb(0x4d, 0xb6, 0xac));
actualDataSet.setCircleColor(Color.rgb(0x4d, 0xb6, 0xac));
actualDataSet.setLineWidth(2f);
if (DISPLAY_PERIOD_DAY == DISPLAY_PERIOD_14DAYS && RICH_INFO) {
actualDataSet.setDrawValues(true);
actualDataSet.setValueTextSize(point.x/(120.0f));
actualDataSet.setValueTextColor(Color.rgb(0x4d, 0xb6, 0xac));
} else {
actualDataSet.setDrawValues(false);
}
dataSets.add(actualDataSet);
LineDataSet actualNightDataSet = new LineDataSet(actualValuesNight, legend + "(" + getString(R.string.graph_legend_night) + ")");
actualNightDataSet.setColor(Color.rgb(255, 166, 0));
actualNightDataSet.setCircleColor(Color.rgb(255, 166, 0));
actualNightDataSet.setLineWidth(2f);
if (DISPLAY_PERIOD_DAY == DISPLAY_PERIOD_14DAYS && RICH_INFO) {
actualNightDataSet.setDrawValues(true);
actualNightDataSet.setValueTextSize(point.x / (120.0f));
actualNightDataSet.setValueTextColor(Color.rgb(255, 166, 0));
} else {
actualNightDataSet.setDrawValues(false);
}
dataSets.add(actualNightDataSet);
return new LineData(dataSets);
}
}
public class XAxisValueFormatter extends ValueFormatter {
Date[] mDateValues;
public XAxisValueFormatter(Date[] dateValues) {
mDateValues = dateValues;
}
@Override
public String getFormattedValue(float value) {
// write your logic here
int val = (int) value;
SimpleDateFormat sdf = new SimpleDateFormat("MM/dd",Locale.getDefault());
if (mDateValues[val] != null) {
return sdf.format(mDateValues[val]);
} else {
return String.valueOf(value);
}
}
}
private void reverseOrderDate(Date[] date) {
int size = date.length;
for (int i=0; i<size/2; i++) {
Date temp1 = date[i];
date[i] = date[size-1-i];
date[size-1-i] = temp1;
}
}
private void reverseOrder(double[] values, boolean[] existFlag) {
int size = values.length;
for (int i=0; i<size/2; i++) {
double temp1 = values[i];
values[i] = values[size-1-i];
values[size-1-i] = temp1;
boolean temp2 = existFlag[i];
existFlag[i] = existFlag[size-1-i];
existFlag[size-1-i] = temp2;
}
}
@SuppressWarnings("ConstantConditions")
private class MakeAndDisplayGraph {
public MakeAndDisplayGraph() {
}
//日付時刻文字列を Date型に変換
private Date String2date(String strDate) {
Date dateDate = null;
// 日付文字列→date型変換フォーマットを指定して
SimpleDateFormat sdf1 = new SimpleDateFormat("yyyy/M/d", Locale.JAPAN);
try {
dateDate = sdf1.parse(strDate);
} catch (ParseException e) {
Resources resources = getResources();
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_input_correct_date), Toast.LENGTH_SHORT).show();
}
return dateDate;
}
public void makeAndDisplayGraph(CalendarAction action, int checkedId) {
Resources resources = getResources();
final String strDateMin = "2200/12/31";
final String strDateMax = "1970/1/1";
DatabaseManager databaseManager = new DatabaseManager();
Cursor cursor = databaseManager.queryDatabaseAll();
Date dateMin = String2date(strDateMin);
Date dateMax = String2date(strDateMax);
if (cursor.moveToFirst()) {
do {
Date date = String2date(cursor.getString(cursor.getColumnIndex("date")));
if (date.getTime() < dateMin.getTime()) {
dateMin = date;
}
if (dateMax.getTime() < date.getTime()) {
dateMax = date;
}
} while (cursor.moveToNext());
}
cursor.close();
DataCenter dataCenter = new DataCenter();
Calendar cal_start = dataCenter.getCalendarGraph();
Calendar cal_now = Calendar.getInstance();
switch (action) {
case NEXT:
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
if (cal_now.getTime().getTime() <= cal_start.getTime().getTime()) {
dataCenter.newCalendarGraph();
cal_start = dataCenter.getCalendarGraph();
Toast.makeText(getActivity(),resources.getString(R.string.graph_message_display_latest_data),Toast.LENGTH_SHORT).show();
}
break;
case PREVIOUS:
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
break;
case TODAY:
cal_start = dataCenter.newCalendarGraph();
break;
}
switch (checkedId) {
case R.id.radioButtonWeight: {
Date[] dateValue = new Date[DISPLAY_PERIOD_DAY];
double[] yActualValue = new double[DISPLAY_PERIOD_DAY];
double[] yActualValueNight = new double[DISPLAY_PERIOD_DAY];
double[] yTargetValue = new double[DISPLAY_PERIOD_DAY];
boolean[] existFlagActual = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagActualNight = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagTarget = new boolean[DISPLAY_PERIOD_DAY];
int year = cal_start.get(Calendar.YEAR);
int month = cal_start.get(Calendar.MONTH) + 1;
int date = cal_start.get(Calendar.DATE);
Calendar cal_index = Calendar.getInstance();
cal_index.set(Calendar.YEAR, year);
cal_index.set(Calendar.MONTH, month - 1);
cal_index.set(Calendar.DATE, date);
boolean exist_flag = false;
int dataCount = 0;
for (int i = 0; i < DISPLAY_PERIOD_DAY; i++) {
String strYearMonthDate = String.valueOf(year) + "/" + String.valueOf(month) + "/" + String.valueOf(date);
cursor = databaseManager.queryDatabase(strYearMonthDate);
dateValue[dataCount] = String2date(strYearMonthDate);
if (cursor.moveToFirst()) {
do {
double actualValue = cursor.getDouble(cursor.getColumnIndex("actual_weight"));
double actualValueNight = cursor.getDouble(cursor.getColumnIndex("actual_weight_night"));
double targetValue = cursor.getDouble(cursor.getColumnIndex("target_weight"));
yActualValue[dataCount] = actualValue;
if (actualValue != 0f) {
existFlagActual[dataCount] = true;
exist_flag = true;
} else {
existFlagActual[dataCount] = false;
}
yActualValueNight[dataCount] = actualValueNight;
if (actualValueNight != 0f) {
existFlagActualNight[dataCount] = true;
exist_flag = true;
} else {
existFlagActualNight[dataCount] = false;
}
yTargetValue[dataCount] = targetValue;
if (targetValue != 0f) {
existFlagTarget[dataCount] = true;
exist_flag = true;
} else {
existFlagTarget[dataCount] = false;
}
} while (cursor.moveToNext());
}
cursor.close();
cal_index.add(Calendar.DATE, -1);
year = cal_index.get(Calendar.YEAR);
month = cal_index.get(Calendar.MONTH) + 1;
date = cal_index.get(Calendar.DATE);
dataCount++;
}
Calendar cal_end = Calendar.getInstance();
cal_end.set(Calendar.YEAR, year);
cal_end.set(Calendar.MONTH, month - 1);
cal_end.set(Calendar.DATE, date);
cal_end.add(Calendar.DATE, 1);
if (exist_flag) {
GraphManager graphManager = new GraphManager(getActivity());
graphManager.displayGraph(
resources.getString(R.string.graph_weight),
dataCount,
dateValue,
existFlagActual,
yActualValue,
existFlagActualNight,
yActualValueNight,
existFlagTarget,
yTargetValue);
} else {
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_no_data), Toast.LENGTH_SHORT).show();
switch (action) {
case NEXT:
if (dateMax.getTime() <= cal_start.getTime().getTime()) {
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
}
break;
case PREVIOUS:
if (cal_end.getTime().getTime() <= dateMin.getTime()) {
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
}
break;
}
}
}
break;
case R.id.radioButtonBodyFatPercentage: {
Date[] dateValue = new Date[DISPLAY_PERIOD_DAY];
double[] yActualValue = new double[DISPLAY_PERIOD_DAY];
double[] yActualValueNight = new double[DISPLAY_PERIOD_DAY];
double[] yTargetValue = new double[DISPLAY_PERIOD_DAY];
boolean[] existFlagActual = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagActualNight = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagTarget = new boolean[DISPLAY_PERIOD_DAY];
int year = cal_start.get(Calendar.YEAR);
int month = cal_start.get(Calendar.MONTH) + 1;
int date = cal_start.get(Calendar.DATE);
Calendar cal_index = Calendar.getInstance();
cal_index.set(Calendar.YEAR, year);
cal_index.set(Calendar.MONTH, month - 1);
cal_index.set(Calendar.DATE, date);
boolean exist_flag = false;
int dataCount = 0;
for (int i = 0; i < DISPLAY_PERIOD_DAY; i++) {
String strYearMonthDate = String.valueOf(year) + "/" + String.valueOf(month) + "/" + String.valueOf(date);
cursor = databaseManager.queryDatabase(strYearMonthDate);
dateValue[dataCount] = String2date(strYearMonthDate);
if (cursor.moveToFirst()) {
do {
double actualValue = cursor.getDouble(cursor.getColumnIndex("actual_body_fat_percentage"));
double actualValueNight = cursor.getDouble(cursor.getColumnIndex("actual_body_fat_percentage_night"));
double targetValue = cursor.getDouble(cursor.getColumnIndex("target_body_fat_percentage"));
yActualValue[dataCount] = actualValue;
if (actualValue != 0f) {
existFlagActual[dataCount] = true;
exist_flag = true;
} else {
existFlagActual[dataCount] = false;
}
yActualValueNight[dataCount] = actualValueNight;
if (actualValueNight != 0f) {
existFlagActualNight[dataCount] = true;
exist_flag = true;
} else {
existFlagActualNight[dataCount] = false;
}
yTargetValue[dataCount] = targetValue;
if (targetValue != 0f) {
existFlagTarget[dataCount] = true;
exist_flag = true;
} else {
existFlagTarget[dataCount] = false;
}
} while (cursor.moveToNext());
}
cursor.close();
cal_index.add(Calendar.DATE, -1);
year = cal_index.get(Calendar.YEAR);
month = cal_index.get(Calendar.MONTH) + 1;
date = cal_index.get(Calendar.DATE);
dataCount++;
}
Calendar cal_end = Calendar.getInstance();
cal_end.set(Calendar.YEAR, year);
cal_end.set(Calendar.MONTH, month - 1);
cal_end.set(Calendar.DATE, date);
cal_end.add(Calendar.DATE, 1);
if (exist_flag) {
GraphManager graphManager = new GraphManager(getActivity());
graphManager.displayGraph(
resources.getString(R.string.graph_body_fat_percentage),
dataCount,
dateValue,
existFlagActual,
yActualValue,
existFlagActualNight,
yActualValueNight,
existFlagTarget,
yTargetValue);
} else {
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_no_data), Toast.LENGTH_SHORT).show();
switch (action) {
case NEXT:
if (dateMax.getTime() <= cal_start.getTime().getTime()) {
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
}
break;
case PREVIOUS:
if (cal_end.getTime().getTime() <= dateMin.getTime()) {
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
}
break;
}
}
}
break;
case R.id.radioButtonBMI: {
Date[] dateValue = new Date[DISPLAY_PERIOD_DAY];
double[] yActualValue = new double[DISPLAY_PERIOD_DAY];
double[] yActualValueNight = new double[DISPLAY_PERIOD_DAY];
double[] yTargetValue = new double[DISPLAY_PERIOD_DAY];
boolean[] existFlagActual = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagActualNight = new boolean[DISPLAY_PERIOD_DAY];
boolean[] existFlagTarget = new boolean[DISPLAY_PERIOD_DAY];
int year = cal_start.get(Calendar.YEAR);
int month = cal_start.get(Calendar.MONTH) + 1;
int date = cal_start.get(Calendar.DATE);
Calendar cal_index = Calendar.getInstance();
cal_index.set(Calendar.YEAR, year);
cal_index.set(Calendar.MONTH, month - 1);
cal_index.set(Calendar.DATE, date);
boolean exist_flag = false;
int dataCount = 0;
for (int i = 0; i < DISPLAY_PERIOD_DAY; i++) {
String strYearMonthDate = String.valueOf(year) + "/" + String.valueOf(month) + "/" + String.valueOf(date);
cursor = databaseManager.queryDatabase(strYearMonthDate);
dateValue[dataCount] = String2date(strYearMonthDate);
if (cursor.moveToFirst()) {
do {
double actualValue = cursor.getDouble(cursor.getColumnIndex("actual_BMI"));
double actualValueNight = cursor.getDouble(cursor.getColumnIndex("actual_BMI_night"));
double targetValue = cursor.getDouble(cursor.getColumnIndex("target_BMI"));
yActualValue[dataCount] = actualValue;
if (actualValue != 0f) {
existFlagActual[dataCount] = true;
exist_flag = true;
} else {
existFlagActual[dataCount] = false;
}
yActualValueNight[dataCount] = actualValueNight;
if (actualValueNight != 0f) {
existFlagActualNight[dataCount] = true;
exist_flag = true;
} else {
existFlagActualNight[dataCount] = false;
}
yTargetValue[dataCount] = targetValue;
if (targetValue != 0f) {
existFlagTarget[dataCount] = true;
exist_flag = true;
} else {
existFlagTarget[dataCount] = false;
}
} while (cursor.moveToNext());
}
cursor.close();
cal_index.add(Calendar.DATE, -1);
year = cal_index.get(Calendar.YEAR);
month = cal_index.get(Calendar.MONTH) + 1;
date = cal_index.get(Calendar.DATE);
dataCount++;
}
Calendar cal_end = Calendar.getInstance();
cal_end.set(Calendar.YEAR, year);
cal_end.set(Calendar.MONTH, month - 1);
cal_end.set(Calendar.DATE, date);
cal_end.add(Calendar.DATE, 1);
if (exist_flag) {
GraphManager graphManager = new GraphManager(getActivity());
graphManager.displayGraph(
resources.getString(R.string.graph_BMI),
dataCount,
dateValue,
existFlagActual,
yActualValue,
existFlagActualNight,
yActualValueNight,
existFlagTarget,
yTargetValue);
} else {
Toast.makeText(getActivity(), resources.getString(R.string.graph_message_no_data), Toast.LENGTH_SHORT).show();
switch (action) {
case NEXT:
if (dateMax.getTime() <= cal_start.getTime().getTime()) {
cal_start.add(Calendar.DATE, -(DISPLAY_PERIOD_DAY));
}
break;
case PREVIOUS:
if (cal_end.getTime().getTime() <= dateMin.getTime()) {
cal_start.add(Calendar.DATE, DISPLAY_PERIOD_DAY);
}
break;
}
}
}
break;
}
}
}
実行結果はこんな感じです。