Improved the piechart, added percentage and legend. Added selectionlistener. Improved example.

This commit is contained in:
Philipp Jahoda 2014-04-29 18:34:10 +02:00
parent e16e0da23a
commit a3075e94f2
9 changed files with 248 additions and 34 deletions

View file

@ -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>

View file

@ -41,14 +41,14 @@ public class MultipleChartsActivity extends Activity {
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 @@ public class MultipleChartsActivity extends Activity {
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)));

View file

@ -2,7 +2,6 @@ package com.example.mpchartexample;
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.SeekBar.OnSeekBarChangeListener;
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 @@ public class PieChartActivity extends Activity implements OnSeekBarChangeListene
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 @@ public class PieChartActivity extends Activity implements OnSeekBarChangeListene
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 @@ public class PieChartActivity extends Activity implements OnSeekBarChangeListene
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,12 +135,27 @@ public class PieChartActivity extends Activity implements OnSeekBarChangeListene
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

View file

@ -202,7 +202,7 @@ public class BarChart extends BarLineChartBase {
@Override
public void highlightValues(int[] indices) {
super.highlightValues(indices);
}
/**

View file

@ -694,4 +694,9 @@ public abstract class BarLineChartBase extends Chart {
width = 3.0f;
mGridWidth = width;
}
@Override
protected void highlightValues(int[] indices) {
super.highlightValues(indices);
}
}

View file

@ -122,6 +122,9 @@ public abstract class Chart extends View {
/** 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 @@ public abstract class Chart extends View {
*
* @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);
}
}
}
/**
* ################ ################ ################ ################
@ -867,6 +885,47 @@ public abstract class Chart extends View {
return mDrawValues;
}
/**
* 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

View file

@ -148,7 +148,7 @@ public class LineChart extends BarLineChartBase {
@Override
public void highlightValues(int[] indices) {
super.highlightValues(indices);
}
/**

View file

@ -0,0 +1,7 @@
package com.github.mikephil.charting;
public interface OnChartValueSelectedListener {
public void onValuesSelected(float[] values, int[] indices);
public void onNothingSelected();
}

View file

@ -40,8 +40,11 @@ public class PieChart extends Chart {
/** 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;
@ -49,6 +52,17 @@ public class PieChart extends Chart {
/** if enabled, centertext is drawn */
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
*/
@ -99,8 +113,12 @@ public class PieChart extends Chart {
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 @@ public class PieChart extends Chart {
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 @@ public class PieChart extends Chart {
}
angle += newanlge;
}
}
/**
* draws the hole in the center of the chart
*/
private void drawHole() {
if (mDrawHole) {
@ -320,15 +346,29 @@ public class PieChart extends Chart {
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 @@ public class PieChart extends Chart {
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 @@ public class PieChart extends Chart {
@Override
public void highlightValues(int[] indices) {
super.highlightValues(indices);
mIndicesToHightlight = indices;
invalidate();
}
@ -481,15 +550,21 @@ public class PieChart extends Chart {
}
/**
* 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 class PieChart extends Chart {
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 @@ public class PieChart extends Chart {
if (x > getCenter().x)
angle = 360f - angle;
// add 90° because chart starts EAST
angle = angle + 90f;
// neutralize overflow
@ -599,8 +709,4 @@ public class PieChart extends Chart {
return dist;
}
@Override
protected void drawAdditional() {
}
}