Improved the piechart, added percentage and legend. Added selectionlistener. Improved example.
diff --git a/MPChartExample/res/menu/pie.xml b/MPChartExample/res/menu/pie.xml
index dea60d1..2e21675 100644
--- a/MPChartExample/res/menu/pie.xml
+++ b/MPChartExample/res/menu/pie.xml
@@ -1,7 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
<item android:id="@+id/actionToggleValues" android:title="Toggle Values"></item>
+ <item android:id="@+id/actionToggleXVals" android:title="Toggle X-Values"></item>
+ <item android:id="@+id/actionTogglePercent" android:title="Toggle Percent"></item>
<item android:id="@+id/actionToggleHole" android:title="Toggle Hole"></item>
<item android:id="@+id/actionDrawCenter" android:title="Draw CenterText"></item>
<item android:id="@+id/actionSave" android:title="Save to Gallery"></item>
+
</menu>
diff --git a/MPChartExample/src/com/example/mpchartexample/MultipleChartsActivity.java b/MPChartExample/src/com/example/mpchartexample/MultipleChartsActivity.java
index 410eba5..0e5b89c 100644
--- a/MPChartExample/src/com/example/mpchartexample/MultipleChartsActivity.java
+++ b/MPChartExample/src/com/example/mpchartexample/MultipleChartsActivity.java
@@ -41,14 +41,14 @@
small.add(6f);
for(int i = 0; i < small.size(); i++) {
- xvalsSmall.add(""+i);
+ xvalsSmall.add("Val"+i);
}
ArrayList<Float> large = new ArrayList<Float>();
for(int i = 0; i < 1000; i++) {
large.add((float) (Math.random() * 50));
- xvalsLarge.add(""+i);
+ xvalsLarge.add("Val"+i);
}
mLineChart.setData(xvalsLarge, large);
@@ -69,6 +69,7 @@
mPieChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.FRESH_COLORS)));
// mChart3.highlightValues(new int[] {0, 1, 2, 3, 4} );
mPieChart.setDrawValues(true);
+ mPieChart.setDrawXVals(false);
mBarChart3D.setData(xvalsLarge, large);
mBarChart3D.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.LIBERTY_COLORS)));
diff --git a/MPChartExample/src/com/example/mpchartexample/PieChartActivity.java b/MPChartExample/src/com/example/mpchartexample/PieChartActivity.java
index 10d5e9a..1552a4b 100644
--- a/MPChartExample/src/com/example/mpchartexample/PieChartActivity.java
+++ b/MPChartExample/src/com/example/mpchartexample/PieChartActivity.java
@@ -2,7 +2,6 @@
import android.app.Activity;
import android.os.Bundle;
-import android.os.Handler;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
@@ -12,11 +11,12 @@
import android.widget.TextView;
import com.github.mikephil.charting.ColorTemplate;
+import com.github.mikephil.charting.OnChartValueSelectedListener;
import com.github.mikephil.charting.PieChart;
import java.util.ArrayList;
-public class PieChartActivity extends Activity implements OnSeekBarChangeListener {
+public class PieChartActivity extends Activity implements OnSeekBarChangeListener, OnChartValueSelectedListener {
private PieChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
@@ -41,15 +41,17 @@
mChart = (PieChart) findViewById(R.id.chart1);
mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.COLORFUL_COLORS)));
- mChart.setDrawValues(false);
+ mChart.setDrawValues(true);
mChart.setDrawCenterText(true);
mChart.setDescription("This is a description.");
mChart.setDrawHoleEnabled(true);
-
+ mChart.setDrawXVals(true);
mChart.setTouchEnabled(true);
+ mChart.setUsePercentValues(false);
+ mChart.setOnChartValueSelectedListener(this);
- mSeekBarX.setProgress(10);
+ mSeekBarX.setProgress(5);
mSeekBarY.setProgress(100);
// float diameter = mChart.getDiameter();
@@ -76,6 +78,14 @@
mChart.invalidate();
break;
}
+ case R.id.actionTogglePercent: {
+ if (mChart.isUsePercentValuesEnabled())
+ mChart.setUsePercentValues(false);
+ else
+ mChart.setUsePercentValues(true);
+ mChart.invalidate();
+ break;
+ }
case R.id.actionToggleHole: {
if (mChart.isDrawHoleEnabled())
mChart.setDrawHoleEnabled(false);
@@ -92,6 +102,14 @@
mChart.invalidate();
break;
}
+ case R.id.actionToggleXVals: {
+ if (mChart.isDrawXValsEnabled())
+ mChart.setDrawXVals(false);
+ else
+ mChart.setDrawXVals(true);
+ mChart.invalidate();
+ break;
+ }
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title"+System.currentTimeMillis(), "");
@@ -117,13 +135,28 @@
ArrayList<String> xVals = new ArrayList<String>();
- for(int i = 0; i < yVals.size(); i++) xVals.add(""+i);
+ for(int i = 0; i < yVals.size(); i++) xVals.add("Text"+(i+1));
mChart.setData(xVals, yVals);
+ mChart.setCenterText("Total Value\n" + (int) mChart.getYValueSum() + "\n(all slices)");
mChart.invalidate();
}
+
+ @Override
+ public void onValuesSelected(float[] values, int[] indices) {
+ StringBuffer a = new StringBuffer();
+
+ for(int i = 0; i < values.length; i++) a.append("val: " + values[i] + ", ind: " + indices[i] + "\n");
+
+ Log.i("PieChart", "Selected: " + a.toString());
+ }
@Override
+ public void onNothingSelected() {
+ Log.i("PieChart", "nothing selected");
+ }
+
+ @Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
diff --git a/MPChartLib/src/com/github/mikephil/charting/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/BarChart.java
index d212347..0773b4f 100644
--- a/MPChartLib/src/com/github/mikephil/charting/BarChart.java
+++ b/MPChartLib/src/com/github/mikephil/charting/BarChart.java
@@ -202,7 +202,7 @@
@Override
public void highlightValues(int[] indices) {
-
+ super.highlightValues(indices);
}
/**
diff --git a/MPChartLib/src/com/github/mikephil/charting/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/BarLineChartBase.java
index 6a0a4b6..f4a67ac 100644
--- a/MPChartLib/src/com/github/mikephil/charting/BarLineChartBase.java
+++ b/MPChartLib/src/com/github/mikephil/charting/BarLineChartBase.java
@@ -694,4 +694,9 @@
width = 3.0f;
mGridWidth = width;
}
+
+ @Override
+ protected void highlightValues(int[] indices) {
+ super.highlightValues(indices);
+ }
}
diff --git a/MPChartLib/src/com/github/mikephil/charting/Chart.java b/MPChartLib/src/com/github/mikephil/charting/Chart.java
index 36fe338..2508cd2 100644
--- a/MPChartLib/src/com/github/mikephil/charting/Chart.java
+++ b/MPChartLib/src/com/github/mikephil/charting/Chart.java
@@ -122,6 +122,9 @@
/** this rectangle defines the area in which graph values can be drawn */
protected Rect mContentRect;
+ /** listener that is called when a value on the chart is selected */
+ protected OnChartValueSelectedListener mSelectionListener;
+
/** default constructor for initialization in code */
public Chart(Context context) {
super(context);
@@ -482,7 +485,22 @@
*
* @param indices
*/
- public abstract void highlightValues(int[] indices);
+ protected void highlightValues(int[] indices) {
+
+ if(mSelectionListener != null) {
+
+ if(indices[0] == -1) mSelectionListener.onNothingSelected();
+ else {
+
+ float[] values = new float[indices.length];
+
+ for(int i = 0; i < values.length; i++) values[i] = getYValue(indices[i]);
+
+ // notify the listener
+ mSelectionListener.onValuesSelected(values, indices);
+ }
+ }
+ }
/**
* ################ ################ ################ ################
@@ -868,6 +886,47 @@
}
/**
+ * returns the y-value at the given index
+ *
+ * @param index
+ * @return
+ */
+ public float getYValue(int index) {
+ return mYVals.get(index);
+ }
+
+ /**
+ * returns the x-value at the given index
+ *
+ * @param index
+ * @return
+ */
+ public String getXValue(int index) {
+ if (mXVals == null || mXVals.size() >= index)
+ return null;
+ else
+ return mXVals.get(index);
+ }
+
+ /**
+ * returns the percentage the given value has of the total y-values
+ *
+ * @param val
+ * @return
+ */
+ public float getPercentOfTotal(float val) {
+ return val / mYValueSum * 100f;
+ }
+
+ /**
+ * set a selection listener for the chart
+ * @param l
+ */
+ public void setOnChartValueSelectedListener(OnChartValueSelectedListener l) {
+ this.mSelectionListener = l;
+ }
+
+ /**
* saves the current chart state to a bitmap in the gallery NOTE: Needs
* permission WRITE_EXTERNAL_STORAGE
*
diff --git a/MPChartLib/src/com/github/mikephil/charting/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/LineChart.java
index 9a94374..94696db 100644
--- a/MPChartLib/src/com/github/mikephil/charting/LineChart.java
+++ b/MPChartLib/src/com/github/mikephil/charting/LineChart.java
@@ -148,7 +148,7 @@
@Override
public void highlightValues(int[] indices) {
-
+ super.highlightValues(indices);
}
/**
diff --git a/MPChartLib/src/com/github/mikephil/charting/OnChartValueSelectedListener.java b/MPChartLib/src/com/github/mikephil/charting/OnChartValueSelectedListener.java
new file mode 100644
index 0000000..8b13476
--- /dev/null
+++ b/MPChartLib/src/com/github/mikephil/charting/OnChartValueSelectedListener.java
@@ -0,0 +1,7 @@
+package com.github.mikephil.charting;
+
+public interface OnChartValueSelectedListener {
+
+ public void onValuesSelected(float[] values, int[] indices);
+ public void onNothingSelected();
+}
diff --git a/MPChartLib/src/com/github/mikephil/charting/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/PieChart.java
index a10f5f2..d88ffa6 100644
--- a/MPChartLib/src/com/github/mikephil/charting/PieChart.java
+++ b/MPChartLib/src/com/github/mikephil/charting/PieChart.java
@@ -40,8 +40,11 @@
/** if true, the white hole inside the chart will be drawn */
private boolean mDrawHole = true;
- private String mCenterTextLine1 = "Total Value";
- private String mCenterTextLine2 = "";
+ /**
+ * variable for the text that is drawn in the center of the pie-chart. If
+ * this value is null, the default is "Total Value\n + getYValueSum()"
+ */
+ private String mCenterText = null;
/** indicates the selection distance of a pie slice */
private float mShift = 20f;
@@ -50,6 +53,17 @@
private boolean mDrawCenterText = true;
/**
+ * set this to true to draw the x-values next to the values in the pie
+ * slices
+ */
+ private boolean mDrawXVals = true;
+
+ /**
+ * if set to true, all values show up in percent instead of their real value
+ */
+ private boolean mUsePercentValues = false;
+
+ /**
* array of integers that reference the highlighted slices in the pie chart
*/
private int[] mIndicesToHightlight = new int[0];
@@ -99,8 +113,12 @@
mValuePaint.setTextSize(Utils.convertDpToPixel(13f));
mValuePaint.setColor(Color.WHITE);
+ mValuePaint.setTextAlign(Align.CENTER);
mListener = new PieChartTouchListener(this);
+
+ // for the piechart, drawing values is enabled
+ mDrawValues = true;
}
@Override
@@ -140,7 +158,9 @@
return;
calcMinMax();
- mCenterTextLine2 = "" + (int) getYValueSum();
+
+ if (mCenterText == null)
+ mCenterText = "Total Value\n" + (int) getYValueSum();
// calculate how many digits are needed
calcFormats();
@@ -302,6 +322,12 @@
}
angle += newanlge;
}
+ }
+
+ /**
+ * draws the hole in the center of the chart
+ */
+ private void drawHole() {
if (mDrawHole) {
@@ -320,15 +346,29 @@
PointF c = getCenter();
- mDrawCanvas.drawText(mCenterTextLine1, c.x, c.y, mCenterTextPaint);
- mDrawCanvas.drawText(mCenterTextLine2, c.x, c.y + mCenterTextPaint.getTextSize() + 3,
- mCenterTextPaint);
+ // get all lines from the text
+ String[] lines = mCenterText.split("\n");
+
+ // calculate the height for each line
+ float lineHeight = (mValuePaint.ascent() + mValuePaint.descent()) * 1.6f;
+
+ // calculate the height of the whole text
+ float textheight = lines.length * lineHeight;
+
+ for (int i = 0; i < lines.length; i++) {
+ mDrawCanvas.drawText(lines[lines.length - i - 1], c.x, c.y - textheight/2 + lineHeight * i,
+ mCenterTextPaint);
+ }
}
}
@Override
protected void drawValues() {
+ // if neither xvals nor yvals are drawn, return
+ if (!mDrawXVals && !mDrawValues)
+ return;
+
PointF center = getCenter();
float off = mCircleBox.width() / 8;
@@ -352,15 +392,43 @@
float y = (float) (r
* Math.sin(Math.toRadians(mChartAngle + mAbsoluteAngles[i] - offset)) + center.y);
- if (y > center.y) {
- y += 10;
- x += 3;
- }
+ // if (y > center.y) {
+ // y += 10;
+ // x += 3;
+ // }
+
+ String val = "";
+
+ if(mUsePercentValues) val = mFormatValue.format(getPercentOfTotal(mYVals.get(i))) + " %";
+ else val = mFormatValue.format(mYVals.get(i));
- mDrawCanvas.drawText(mFormatValue.format(mYVals.get(i)), x, y, mValuePaint);
+ // draw everything, depending on settings
+ if (mDrawXVals && mDrawValues) {
+
+ // use ascent and descent to calculate the new line position,
+ // 1.6f is the line spacing
+ float lineHeight = (mValuePaint.ascent() + mValuePaint.descent()) * 1.6f;
+ y -= lineHeight / 2;
+
+ mDrawCanvas.drawText(val, x,
+ y, mValuePaint);
+ mDrawCanvas.drawText(mXVals.get(i), x,
+ y + lineHeight, mValuePaint);
+
+ } else if (mDrawXVals && !mDrawValues) {
+ mDrawCanvas.drawText(mXVals.get(i), x, y, mValuePaint);
+ } else if (!mDrawXVals && mDrawValues) {
+
+ mDrawCanvas.drawText(val, x, y, mValuePaint);
+ }
}
}
+ @Override
+ protected void drawAdditional() {
+ drawHole();
+ }
+
/**
* checks if the given index is set for highlighting or not
*
@@ -388,7 +456,8 @@
@Override
public void highlightValues(int[] indices) {
-
+ super.highlightValues(indices);
+
mIndicesToHightlight = indices;
invalidate();
}
@@ -481,15 +550,21 @@
}
/**
- * sets the text that is displayed in the center of the pie-chart (2 lines
- * available)
+ * sets the text that is displayed in the center of the pie-chart. By
+ * default, the text is "Total Value + sumofallvalues"
*
- * @param line1
- * @param line2
+ * @param text
*/
- public void setCenterText(String line1, String line2) {
- mCenterTextLine1 = line1;
- mCenterTextLine2 = line2;
+ public void setCenterText(String text) {
+ mCenterText = text;
+ }
+
+ /**
+ * returns the text that is drawn in the center of the pie-chart
+ * @return
+ */
+ public String getCenterText() {
+ return mCenterText;
}
/**
@@ -510,6 +585,40 @@
public boolean isDrawCenterTextEnabled() {
return mDrawCenterText;
}
+
+ /**
+ * set this to true to draw percent values instead of the actual values
+ * @param enabled
+ */
+ public void setUsePercentValues(boolean enabled) {
+ mUsePercentValues = enabled;
+ }
+
+ /**
+ * returns true if drawing percent values is enabled
+ * @return
+ */
+ public boolean isUsePercentValuesEnabled() {
+ return mUsePercentValues;
+ }
+
+ /**
+ * set this to true to draw the x-value text into the pie slices
+ *
+ * @param enabled
+ */
+ public void setDrawXVals(boolean enabled) {
+ mDrawXVals = enabled;
+ }
+
+ /**
+ * returns true if drawing x-values is enabled, false if not
+ *
+ * @return
+ */
+ public boolean isDrawXValsEnabled() {
+ return mDrawXVals;
+ }
/**
* returns the radius of the pie-chart
@@ -556,6 +665,7 @@
if (x > getCenter().x)
angle = 360f - angle;
+ // add 90° because chart starts EAST
angle = angle + 90f;
// neutralize overflow
@@ -599,8 +709,4 @@
return dist;
}
-
- @Override
- protected void drawAdditional() {
- }
}