Major improvements to the Legend, Legend now groups colors of the same DataSet. Worked on examples.

This commit is contained in:
Philipp Jahoda 2014-07-26 15:31:39 +02:00
parent ff01a15210
commit a6f35d574e
15 changed files with 223 additions and 72 deletions

View file

@ -41,6 +41,7 @@ public class BarChartActivityMultiDataset extends Activity implements OnSeekBarC
mSeekBarY.setOnSeekBarChangeListener(this);
mChart = (BarChart) findViewById(R.id.chart1);
mChart.setDescription("");
ColorTemplate ct = new ColorTemplate();
@ -182,9 +183,9 @@ public class BarChartActivityMultiDataset extends Activity implements OnSeekBarC
}
// create 3 datasets with different types
DataSet set1 = new DataSet(yVals1, "DS 1");
DataSet set2 = new DataSet(yVals2, "DS 2");
DataSet set3 = new DataSet(yVals3, "DS 3");
DataSet set1 = new DataSet(yVals1, "Company A");
DataSet set2 = new DataSet(yVals2, "Company B");
DataSet set3 = new DataSet(yVals3, "Company C");
ArrayList<DataSet> dataSets = new ArrayList<DataSet>();
dataSets.add(set1);

View file

@ -139,8 +139,6 @@ public class LineChartActivity extends Activity implements OnSeekBarChangeListen
// l.setPosition(LegendPosition.LEFT_OF_CHART);
l.setForm(LegendForm.LINE);
mChart.setOffsets(100, 100, 200, 200);
// dont forget to refresh the drawing
mChart.invalidate();
}

View file

@ -22,8 +22,9 @@ public class BarChartFrag extends SimpleFragment {
View v = inflater.inflate(R.layout.frag_simple_bar, container, false);
mChart = (BarChart) v.findViewById(R.id.barChart1);
mChart.setYLabelCount(6);
mChart.setData(generateData());
mChart.setData(generateData(1, 2000000));
return v;
}

View file

@ -1,12 +1,14 @@
package com.example.mpchartexample.simple;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.mpchartexample.R;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.utils.ColorTemplate;
public class LineChartFrag extends SimpleFragment {
@ -23,7 +25,20 @@ public class LineChartFrag extends SimpleFragment {
mChart = (LineChart) v.findViewById(R.id.lineChart1);
mChart.setData(generateData());
ColorTemplate ct = new ColorTemplate();
ct.addColorsForDataSets(new int[] { R.color.vordiplom_1, R.color.vordiplom_4 }, getActivity());
Log.i("TEST", "size: " + ct.getColors().size());
mChart.setColorTemplate(ct);
mChart.setDescription("");
mChart.setDrawFilled(true);
mChart.setDrawYValues(false);
mChart.setLineWidth(3.5f);
mChart.setCircleSize(5f);
mChart.setData(generateData(2, 10000));
return v;
}

View file

@ -5,9 +5,12 @@ import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import com.example.mpchartexample.MyMarkerView;
import com.example.mpchartexample.R;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.charts.ScatterChart;
import com.github.mikephil.charting.charts.BarLineChartBase.BorderStyle;
import com.github.mikephil.charting.charts.ScatterChart.ScatterShape;
import com.github.mikephil.charting.utils.ColorTemplate;
public class ScatterChartFrag extends SimpleFragment {
@ -23,8 +26,32 @@ public class ScatterChartFrag extends SimpleFragment {
View v = inflater.inflate(R.layout.frag_simple_scatter, container, false);
mChart = (ScatterChart) v.findViewById(R.id.scatterChart1);
mChart.setDrawYValues(false);
mChart.setDescription("");
mChart.setData(generateData());
ColorTemplate ct = new ColorTemplate();
ct.addDataSetColors(ColorTemplate.VORDIPLOM_COLORS, getActivity());
ct.addDataSetColors(new int[] { R.color.colorful_1, R.color.colorful_2, R.color.colorful_3 } , getActivity());
ct.addDataSetColors(ColorTemplate.PASTEL_COLORS, getActivity());
mChart.setColorTemplate(ct);
MyMarkerView mv = new MyMarkerView(getActivity(), R.layout.custom_marker_view);
mv.setOffsets(-mv.getMeasuredWidth() / 2, -mv.getMeasuredHeight());
mChart.setMarkerView(mv);
mChart.setScatterShapes(new ScatterShape[] {ScatterShape.CIRCLE, ScatterShape.SQUARE, ScatterShape.TRIANGLE });
mChart.setScatterShapeSize(18f);
mChart.setHighlightIndicatorEnabled(false);
mChart.setDrawBorder(false);
// mChart.setBorderStyles(new BorderStyle[] { BorderStyle.LEFT });
mChart.setDrawGridBackground(false);
mChart.setDrawVerticalGrid(false);
mChart.setDrawXLabels(false);
mChart.setData(generateData(3, 1000));
return v;
}

View file

@ -7,6 +7,7 @@ import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentManager;
import android.support.v4.app.FragmentPagerAdapter;
import android.support.v4.view.ViewPager;
import android.view.WindowManager;
/**
* Demonstrates how to keep your charts straight forward, simple and beautiful with the MPAndroidChart library.
@ -18,6 +19,8 @@ public class SimpleChartDemo extends FragmentActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
ViewPager pager = new ViewPager(this);
pager.setId(1000);

View file

@ -11,32 +11,28 @@ import java.util.ArrayList;
public abstract class SimpleFragment extends Fragment {
/**
* generates some random data, (2 DataSets, 2x20 values)
* generates some random data
* @return
*/
protected ChartData generateData() {
protected ChartData generateData(int dataSets, float range) {
int count = 20;
ArrayList<String> xVals = new ArrayList<String>();
ArrayList<Entry> entries1 = new ArrayList<Entry>();
ArrayList<Entry> entries2 = new ArrayList<Entry>();
for(int i = 0; i < count; i++) {
xVals.add("entry" + (i+1));
entries1.add(new Entry((float) (Math.random() * 10000), i));
entries2.add(new Entry((float) (Math.random() * 10000), i));
}
DataSet ds1 = new DataSet(entries1, "Company A");
DataSet ds2 = new DataSet(entries1, "Company B");
int count = 12;
ArrayList<DataSet> sets = new ArrayList<DataSet>();
sets.add(ds1);
sets.add(ds2);
ChartData d = new ChartData(xVals, sets);
for(int i = 0; i < dataSets; i++) {
ArrayList<Entry> entries = new ArrayList<Entry>();
for(int j = 0; j < count; j++) {
entries.add(new Entry((float) (Math.random() * range), j));
}
DataSet ds = new DataSet(entries, getLabel(i));
sets.add(ds);
}
ChartData d = new ChartData(getXVals(), sets);
return d;
}
@ -67,4 +63,15 @@ public abstract class SimpleFragment extends Fragment {
ChartData d = new ChartData(xVals, ds1);
return d;
}
private String[] mLabels = new String[] { "Company A", "Company B", "Company C", "Company D", "Company E", "Company F" };
private String[] mXVals = new String[] { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Okt", "Nov", "Dec" };
private String getLabel(int i) {
return mLabels[i];
}
private String[] getXVals() {
return mXVals;
}
}

View file

@ -18,7 +18,7 @@ import com.github.mikephil.charting.utils.ColorTemplate;
public class BarChart extends BarLineChartBase {
/** space indicator between the bars 0.1f == 10 % */
private float mBarSpace = 0.1f;
private float mBarSpace = 0.15f;
/** indicates the angle of the 3d effect */
private float mSkew = 0.3f;

View file

@ -447,23 +447,33 @@ public abstract class BarLineChartBase extends Chart {
*/
public void prepareLegend() {
String[] labels = new String[mCt.getColorCount()];
int cnt = 0;
ArrayList<String> labels = new ArrayList<String>();
ArrayList<Integer> colors = new ArrayList<Integer>();
for (int i = 0; i < mCt.getColors().size(); i++) {
for (int j = 0; j < mCt.getColors().get(i).size(); j++) {
for (int i = 0; i < mOriginalData.getDataSetCount(); i++) {
if (i < mOriginalData.getDataSetCount()) {
ArrayList<Integer> clrs = mCt.getDataSetColors(i % mCt.getColors().size());
labels[cnt] = mOriginalData.getDataSetByIndex(i).getLabel();
cnt++;
for (int j = 0; j < clrs.size(); j++) {
// if multiple colors are set for a DataSet, group them
if(j < clrs.size()-1) {
labels.add(null);
} else { // add label to the last entry
String label = mOriginalData.getDataSetByIndex(i).getLabel();
labels.add(label);
}
colors.add(clrs.get(j));
}
}
Legend l = new Legend(mCt.getColorsAsArray(), labels);
Legend l = new Legend(colors, labels);
if (mLegend != null) {
// apply the old legend settings to a potential new legend
l.apply(mLegend);
}
@ -508,17 +518,16 @@ public abstract class BarLineChartBase extends Chart {
for (int i = 0; i < labels.length; i++) {
if (labels[i] == null)
break;
mLegend.drawForm(mDrawCanvas, posX, posY, mLegendFormPaint, i);
// make a step to the left
posX += formToTextSpace;
mLegend.drawLabel(mDrawCanvas, posX, posY + textDrop, mLegendLabelPaint, i);
posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + entrySpace;
if(labels[i] != null) {
mLegend.drawLabel(mDrawCanvas, posX, posY + textDrop, mLegendLabelPaint, i);
posX += Utils.calcTextWidth(mLegendLabelPaint, labels[i]) + entrySpace;
}
}
break;
@ -526,19 +535,32 @@ public abstract class BarLineChartBase extends Chart {
posX = getWidth() - mOffsetRight + formSize;
posY = mOffsetTop;
float stack = 0f;
boolean wasStacked = false;
for (int i = 0; i < labels.length; i++) {
if (labels[i] == null)
break;
mLegend.drawForm(mDrawCanvas, posX + stack, posY, mLegendFormPaint, i);
if(labels[i] != null) {
if(!wasStacked) {
mLegend.drawLabel(mDrawCanvas, posX + formToTextSpace, posY + textDrop,
mLegendLabelPaint, i);
} else {
mLegend.drawLabel(mDrawCanvas, posX, posY + textDrop + entrySpace,
mLegendLabelPaint, i);
posY += entrySpace;
}
mLegend.drawForm(mDrawCanvas, posX, posY, mLegendFormPaint, i);
mLegend.drawLabel(mDrawCanvas, posX + formToTextSpace, posY + textDrop,
mLegendLabelPaint, i);
// make a step down
posY += entrySpace;
// make a step down
posY += entrySpace;
stack = 0f;
} else {
stack += formSize + 4f;
wasStacked = true;
}
}
break;
@ -1249,7 +1271,7 @@ public abstract class BarLineChartBase extends Chart {
public boolean hasFixedYValues() {
return mFixedYValues;
}
/**
* sets the color for the grid lines
*

View file

@ -245,7 +245,7 @@ public abstract class Chart extends View {
yVals.add(new Entry(val, j));
}
DataSet set = new DataSet(yVals, "DS " + i);
DataSet set = new DataSet(yVals, "DataSet " + i);
dataSets.add(set); // add the datasets
}
// create a data object with the datasets
@ -913,6 +913,8 @@ public abstract class Chart extends View {
*/
public void setColorTemplate(ColorTemplate ct) {
this.mCt = ct;
Log.i(LOG_TAG, "ColorTemplate set.");
}
/**

View file

@ -26,7 +26,7 @@ public class DataSet {
private float mYValueSum = 0f;
/** label that describes the DataSet or the data the DataSet represents */
private String mLabel = "";
private String mLabel = "DataSet";
/**

View file

@ -128,6 +128,19 @@ public class ColorTemplate {
}
}
/**
* Adds a single color for one DataSet. Each call of this method will add
* one more color for one DataSet to the template.
*
* @param color
* @param c
*/
public void addDataSetColor(int color, Context c) {
addDataSetColors(new int[] {
color
}, c);
}
/**
* Returns all color arrays the template represents.
*

View file

@ -5,6 +5,8 @@ import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Typeface;
import java.util.ArrayList;
/**
* Class representing the legend of the chart.
*
@ -74,6 +76,28 @@ public class Legend {
this.mLegendLabels = labels;
}
/**
* Constructor. Provide colors and labels for the legend.
*
* @param colors
* @param labels
*/
public Legend(ArrayList<Integer> colors, ArrayList<String> labels) {
this();
if (colors == null || labels == null) {
throw new IllegalArgumentException("colors array or labels array is NULL");
}
if (colors.size() != labels.size()) {
throw new IllegalArgumentException(
"colors array and labels array need to be of same size");
}
this.mColors = Utils.convertIntegers(colors);
this.mLegendLabels = Utils.convertStrings(labels);
}
/**
* returns the maximum length in pixels over all legend labels + their forms
*
@ -85,9 +109,9 @@ public class Legend {
int max = 0;
for (int i = 0; i < mLegendLabels.length; i++) {
if(mLegendLabels[i] != null) {
if (mLegendLabels[i] != null) {
int length = Utils.calcTextWidth(p, mLegendLabels[i]);
if (length > max)
@ -119,6 +143,7 @@ public class Legend {
/**
* Sets a custom array of labels for the legend. Make sure the labels array
* has the same length as the colors array.
*
* @param labels
*/
public void setLegendLabels(String[] labels) {
@ -286,13 +311,15 @@ public class Legend {
c.drawText(mLegendLabels[index], x, y, p);
}
/**
* applies the state from the legend in the parameter to this legend (except colors and labels)
* applies the state from the legend in the parameter to this legend (except
* colors and labels)
*
* @param l
*/
public void apply(Legend l) {
mPosition = l.mPosition;
mShape = l.mShape;
mTypeface = l.mTypeface;

View file

@ -7,6 +7,7 @@ import android.graphics.Rect;
import android.util.DisplayMetrics;
import java.text.DecimalFormat;
import java.util.ArrayList;
/**
* utilities class that has some helper methods
@ -75,7 +76,7 @@ public abstract class Utils {
float dp = px / (metrics.densityDpi / 160f);
return dp;
}
/**
* calculates the approximate width of a text, depending on a demo text
* avoid repeated calls (e.g. inside drawing methods)
@ -209,20 +210,20 @@ public abstract class Utils {
out[ind--] = ',';
charCount++;
decimalPointAdded = true;
// add thousand separators
// add thousand separators
} else if (separateThousands && lval != 0 && charCount > digitCount) {
if(decimalPointAdded) {
if((charCount - digitCount) % 4 == 0) {
if (decimalPointAdded) {
if ((charCount - digitCount) % 4 == 0) {
out[ind--] = '.';
charCount++;
}
} else {
if((charCount - digitCount) % 4 == 3) {
if ((charCount - digitCount) % 4 == 3) {
out[ind--] = '.';
charCount++;
}
@ -254,4 +255,38 @@ public abstract class Utils {
final long shifted = Math.round(number * magnitude);
return shifted / magnitude;
}
/**
* Converts the provided Integer ArrayList to an int array.
*
* @param integers
* @return
*/
public static int[] convertIntegers(ArrayList<Integer> integers) {
int[] ret = new int[integers.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = integers.get(i).intValue();
}
return ret;
}
/**
* Converts the provided String ArrayList to a String array.
*
* @param labels
* @return
*/
public static String[] convertStrings(ArrayList<String> strings) {
String[] ret = new String[strings.size()];
for (int i = 0; i < ret.length; i++) {
ret[i] = strings.get(i);
}
return ret;
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB