之前的记账软件中,加入了GitHub上的开源项目,MPAndroid。
现在介绍一下饼状图。
首先将MPAndroidChart的jar包导入到libs中,jar包的链接可以去girhub下载,进去找不到的话把页面往下面拉拉,就有,网址如下:https://github.com/PhilJay/MPAndroidChart/releases
其中还需要nineoldandroids-2.4.0.jar这个jar包。
链接这里:http://download.csdn.net/detail/chase_java/9689747
导入以后就可以使用了。
建立一个布局文件,加入PieChart。
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/check_income_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="收入"
android:gravity="center"
android:textSize="25sp" />
<com.github.mikephil.charting.charts.PieChart
android:padding="5dp"
android:id="@+id/piechart"
android:layout_width="match_parent"
android:layout_height="match_parent">
com.github.mikephil.charting.charts.PieChart>
LinearLayout>
下面是一个简单的演示:
public class MainActivity extends Activity {
private PieChart mChart;
private String[] x = new String[] { "A类事物", "B类事物", "C类事物" };
// 凑成100 % 100
private float[] y = { 10f, 60f, 30f };
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mChart = (PieChart) findViewById(R.id.piechart);
// 图的描述
mChart.setDescription("在这里输入描述,右下角显示");
// 以3个对应数据集做测试
setData(x.length);
}
private void setData(int count) {
// 准备x"轴"数据:在i的位置,显示x[i]字符串
ArrayList xVals = new ArrayList();
// 真实的饼状图百分比分区。
// Entry包含两个重要数据内容:position和该position的数值。
ArrayList yVals = new ArrayList();
for (int xi = 0; xi < count; xi++) {
xVals.add(xi, x[xi]);
// y[i]代表在x轴的i位置真实的百分比占
yVals.add(new Entry(y[xi], xi));
}
PieDataSet yDataSet = new PieDataSet(yVals, "百分比占");
// 每个百分比占区块绘制的不同颜色
ArrayList colors = new ArrayList();
colors.add(Color.RED);
colors.add(Color.GREEN);
colors.add(Color.BLUE);
yDataSet.setColors(colors);
// 将x轴和y轴设置给PieData作为数据源
PieData data = new PieData(xVals, yDataSet);
// 设置成PercentFormatter将追加%号
data.setValueFormatter(new PercentFormatter());
// 文字的颜色
data.setValueTextColor(Color.BLACK);
// 最终将全部完整的数据喂给PieChart
mChart.setData(data);
mChart.invalidate();
}
}
上面是一个简单的演示,下面为我自己使用的状况:
在Activity中设置饼图的数据:饼图需要加进去的是一个XValues和YValues的数据,其中XValues加入的是种类,Vvalues加入的是种类对应的数值,可以算出百分比后加进去。我这里使用前面的记账软件的sqlite中的数据作为数据源,计算账单收入的占比,
package com.chase.cn.demon;
import android.app.Activity;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.graphics.Color;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.widget.TextView;
import com.github.mikephil.charting.charts.PieChart;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.PieData;
import com.github.mikephil.charting.data.PieDataSet;
import com.github.mikephil.charting.formatter.PercentFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Map;
/**
* Created by Chase on 2016/11/18.
*/
public class Check_Income extends Activity {
private PieChart mChart;
private TextView Income_Detail;
//数据库
private MySQLiteOpenHelper mSqlHelper;
private SQLiteDatabase mDataBase;
private int cursor_income = 0;//X指标数,用于Cursor中的计数统计,问题在于cursor遍历时对于同种类型需要合并
private float sumQuarterly = 0;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.check_income);
mChart = (PieChart) findViewById(R.id.piechart);
Income_Detail = (TextView) findViewById(R.id.check_income_text);
PieData mPieData = getPieData(cursor_income, sumQuarterly);
showChart(mChart, mPieData);
}
//初始化饼状图的数据和设置 顺便监听点击事件 显示TextView的明细
private void showChart(final PieChart mChart, PieData mPieData) {
mChart.setTransparentCircleColor(Color.WHITE);
mChart.setHoleRadius(60f); //半径
mChart.setTransparentCircleRadius(64f); // 半透明圈
//pieChart.setHoleRadius(0) //实心圆
mChart.setDescription("收入情况");//设置描述
mChart.setDrawCenterText(true); //饼状图中间可以添加文字
mChart.setDrawHoleEnabled(true);
mChart.setRotationAngle(90); // 初始旋转角度
// draws the corresponding description value into the slice
mChart.setDrawSlicesUnderHole(true);
mChart.setRotationEnabled(true); // 可以手动旋转
mChart.setUsePercentValues(true); //显示成百分比
mChart.setCenterText("点击查看收入情况"); //饼状图中间的文字
//点击饼块的监听
mChart.setOnChartValueSelectedListener(new OnChartValueSelectedListener() {
@Override
public void onValueSelected(Entry entry, int i, Highlight highlight) {
Log.i("value", "clicked" + entry.getVal());//得到百分值
String value = "" + entry.getVal();
Income_Detail.setText(value);
mChart.setCenterText(value);
}
@Override
public void onNothingSelected() {
}
});
//设置数据
mChart.setData(mPieData);
// undo all highlights
// pieChart.highlightValues(null);
mChart.invalidate();
//比例图为下面标识的方块
Legend mLegend = mChart.getLegend(); //设置比例图
//设置比例块左上显示,设置换行
mLegend.setPosition(Legend.LegendPosition.ABOVE_CHART_LEFT);
mLegend.setWordWrapEnabled(true);
mLegend.setDirection(Legend.LegendDirection.LEFT_TO_RIGHT);
mLegend.setForm(Legend.LegendForm.CIRCLE); //设置比例图的形状,默认是方形
//设置距离饼图的距离
mLegend.setXEntrySpace(7f);
mLegend.setYEntrySpace(5f);
mLegend.setFormSize(12f);//比例图字体大小
mChart.animateXY(2000, 2000); //设置动画
// mChart.spin(2000, 0, 360);
}
/**
* @param count 分成几部分
* @param range
*/
private PieData getPieData(int count, float range) {
ArrayList xValues = new ArrayList(); //xVals用来表示每个饼块上的内容
ArrayList yValues = new ArrayList(); //yVals用来表示封装每个饼块的实际数据
// int cursor_income = 0;//X指标数,用于Cursor中的计数统计,问题在于cursor遍历时对于同种类型需要合并
double Fee = 0, resultIncome = 0;
mSqlHelper = new MySQLiteOpenHelper(this, "finance.db", null, 1);
mDataBase = mSqlHelper.getReadableDatabase();
Cursor cursor = mDataBase.rawQuery("select Fee,Budget,Type from finance", null);
//设置标志,以防止多次添加同一个类型,标志的数量
boolean type1 = false, type2 = false, type3 = false, type4 = false, type5 = false, type6 = false, type7 = false, type8 = false, type9 = false, type10 = false;
//同种类型的钱数求和的总数,收入共有10种类型,和array中type2有关。
double Fee1 = 0, Fee2 = 0, Fee3 = 0, Fee4 = 0, Fee5 = 0, Fee6 = 0, Fee7 = 0, Fee8 = 0, Fee9 = 0, Fee10 = 0;
// float sumQuarterly = 0;
//使用一个map来存储同种类型的 收入之和 后面的+=Fee 也用在后面的Y轴设置时for循环,弥补for循环不能动态读取变量
Map fee_type = new HashMap();
if (cursor.getCount() > 0) {
while (cursor.moveToNext()) {
//移动到指定记录
Fee = cursor.getDouble(cursor.getColumnIndex("Fee"));
String budget = cursor.getString(cursor.getColumnIndex("Budget"));
String type = cursor.getString(cursor.getColumnIndex("Type"));
if (budget.equals("收入")) {
// xValues.add(type);
// cursor_income++;
if (type.equals("一般")) {
Fee1 += Fee;
fee_type.put("a1", Fee1);
if (!type1) {
xValues.add(type);
cursor_income++;
type1 = true;
}
} else if (type.equals("报销")) {
Fee2 += Fee;
fee_type.put("a2", Fee2);
if (!type2) {
xValues.add(type);
cursor_income++;
type2 = true;
}
} else if (type.equals("工资")) {
Fee3 += Fee;
fee_type.put("a3", Fee3);
if (!type3) {
xValues.add(type);
cursor_income++;
type3 = true;
}
} else if (type.equals("零花钱")) {
Fee4 += Fee;
fee_type.put("a4", Fee4);
if (!type4) {
xValues.add(type);
cursor_income++;
type4 = true;
}
} else if (type.equals("兼职")) {
Fee5 += Fee;
fee_type.put("a5", Fee5);
if (!type5) {
xValues.add(type);
cursor_income++;
type5 = true;
}
} else if (type.equals("红包")) {
Fee6 += Fee;
fee_type.put("a6", Fee6);
if (!type6) {
xValues.add(type);
cursor_income++;
type6 = true;
}
} else if (type.equals("生活费")) {
Fee7 += Fee;
fee_type.put("a7", Fee7);
if (!type7) {
xValues.add(type);
cursor_income++;
type7 = true;
}
} else if (type.equals("奖金")) {
Fee8 += Fee;
fee_type.put("a8", Fee8);
if (!type8) {
xValues.add(type);
cursor_income++;
type8 = true;
}
} else if (type.equals("投资")) {
Fee9 += Fee;
fee_type.put("a9", Fee9);
if (!type9) {
xValues.add(type);
cursor_income++;
type9 = true;
}
} else if (type.equals("其他")) {
Fee10 += Fee;
fee_type.put("a10", Fee10);
if (!type10) {
xValues.add(type);
cursor_income++;
type10 = true;
}
}
//统计总数收入
resultIncome += Fee;
}
}
}
cursor.close();
mDataBase.close();
mSqlHelper.close();
Log.d("info3", "resultincome " + resultIncome);
Log.d("info3", "resultincome " + cursor_income);
/**
* 问题出在,yValue在添加的时候不能进行判断操作
*
*/
for (int i = 1; i <= 10; i++) {
// float quarterly = ((float) (Fee / resultIncome)) * 100;
// yValues.add(new Entry(i, i - 1));
if (fee_type.get(("a" + i)) != null) {
float quarterly = ((float) (fee_type.get("a" + i) / (float)resultIncome)) * 100;
yValues.add(new Entry(quarterly, i - 1));
Log.d("info2", "== " + fee_type.get("a" + i));
sumQuarterly += quarterly;
Log.d("info5", "== " + quarterly);
Log.d("info5", "== " + sumQuarterly);
}
}
// 饼图数据
/**
*
*
*/
//y轴的集合
PieDataSet yDataSet = new PieDataSet(yValues, "收入类型"/*显示在比例图上*/);
yDataSet.setSliceSpace(0f); //设置个饼状图之间的距离
ArrayList colors = new ArrayList();
// 饼图颜色
for (int i = 0; i < cursor_income; i++) {
int r, g, b;
r = (int) (Math.random() * 255);
g = (int) (Math.random() * 255);
b = (int) (Math.random() * 255);
colors.add(Color.rgb(r, g, b));
}
yDataSet.setColors(colors);
DisplayMetrics metrics = getResources().getDisplayMetrics();
float px = 5 * (metrics.densityDpi / 160f);
yDataSet.setSelectionShift(px); // 选中态多出的长度
PieData pieData = new PieData(xValues, yDataSet);
// 设置成PercentFormatter将追加%号
pieData.setValueFormatter(new PercentFormatter());
return pieData;
}
}