Introduced Series object to represent one entry in the chart. Added functionality to draw multiple lines in one chart. Improved performance when drawing huge amounts of data. Started implementation on data reduction (Douglas-Peucker-Algorithm).

This commit is contained in:
ph1lb4 2014-05-26 17:53:09 +02:00
parent 3a3c0ef9be
commit 846f5cca2d
16 changed files with 4297 additions and 4025 deletions

View file

@ -1,5 +1,7 @@
package com.example.mpchartexample;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
@ -10,161 +12,160 @@ import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.github.mikephil.charting.BarChart;
import com.github.mikephil.charting.BarSeries;
import com.github.mikephil.charting.ChartData;
import com.github.mikephil.charting.ColorTemplate;
import com.github.mikephil.charting.Series;
import java.util.ArrayList;
public class BarChartActivity extends Activity implements OnSeekBarChangeListener {
private BarChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
private BarChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_barchart);
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarX.setOnSeekBarChangeListener(this);
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
mSeekBarY.setOnSeekBarChangeListener(this);
mChart = (BarChart) findViewById(R.id.chart1);
mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.FRESH_COLORS)));
// mChart.setLegendDigits(2);
// mChart.setValueDigits(2);
// mChart.setDrawFilled(true);
// mChart.setRoundedYLegend(false);
// mChart.setStartAtZero(true);
mChart.setDrawYValues(false);
mChart.set3DEnabled(false);
// mChart.setSpacePercent(20, 10);
mChart.setYLegendCount(5);
mChart.setTouchEnabled(true);
mSeekBarX.setProgress(45);
mSeekBarY.setProgress(100);
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_barchart);
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.bar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleRound: {
if (mChart.isYLegendRounded())
mChart.setRoundedYLegend(false);
else
mChart.setRoundedYLegend(true);
mChart.invalidate();
break;
}
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
mChart.invalidate();
break;
}
case R.id.actionToggle3D: {
if (mChart.is3DEnabled())
mChart.set3DEnabled(false);
else
mChart.set3DEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlight: {
if (mChart.isHighlightEnabled())
mChart.setHighlightEnabled(false);
else
mChart.setHighlightEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlightArrow: {
if (mChart.isDrawHighlightArrowEnabled())
mChart.setDrawHighlightArrow(false);
else
mChart.setDrawHighlightArrow(true);
mChart.invalidate();
break;
}
case R.id.actionToggleStartzero: {
if (mChart.isStartAtZeroEnabled())
mChart.setStartAtZero(false);
else
mChart.setStartAtZero(true);
mChart.invalidate();
break;
}
case R.id.actionToggleAdjustXLegend: {
if (mChart.isAdjustXLegendEnabled())
mChart.setAdjustXLegend(false);
else
mChart.setAdjustXLegend(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title"+System.currentTimeMillis(), "");
break;
}
}
return true;
}
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
xVals.add((i)+"");
}
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarX.setOnSeekBarChangeListener(this);
ArrayList<Series> yVals = new ArrayList<Series>();
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
mSeekBarY.setOnSeekBarChangeListener(this);
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress()+1);
float val = (float) (Math.random() * mult * 0.1) + 3;// + (float) ((mult * 0.1) / 10);
yVals.add(new BarSeries(val));
}
tvX.setText(""+ (mSeekBarX.getProgress() + 1));
tvY.setText(""+ (mSeekBarY.getProgress() / 10));
mChart = (BarChart) findViewById(R.id.chart1);
mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.FRESH_COLORS)));
// mChart.setLegendDigits(2);
// mChart.setValueDigits(2);
mChart.setData(xVals, yVals);
mChart.invalidate();
}
// mChart.setDrawFilled(true);
// mChart.setRoundedYLegend(false);
// mChart.setStartAtZero(true);
mChart.setDrawYValues(false);
mChart.set3DEnabled(false);
// mChart.setSpacePercent(20, 10);
mChart.setYLegendCount(5);
mChart.setTouchEnabled(true);
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
mSeekBarX.setProgress(45);
mSeekBarY.setProgress(100);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.bar, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleRound: {
if (mChart.isYLegendRounded())
mChart.setRoundedYLegend(false);
else
mChart.setRoundedYLegend(true);
mChart.invalidate();
break;
}
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
mChart.invalidate();
break;
}
case R.id.actionToggle3D: {
if (mChart.is3DEnabled())
mChart.set3DEnabled(false);
else
mChart.set3DEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlight: {
if (mChart.isHighlightEnabled())
mChart.setHighlightEnabled(false);
else
mChart.setHighlightEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlightArrow: {
if (mChart.isDrawHighlightArrowEnabled())
mChart.setDrawHighlightArrow(false);
else
mChart.setDrawHighlightArrow(true);
mChart.invalidate();
break;
}
case R.id.actionToggleStartzero: {
if (mChart.isStartAtZeroEnabled())
mChart.setStartAtZero(false);
else
mChart.setStartAtZero(true);
mChart.invalidate();
break;
}
case R.id.actionToggleAdjustXLegend: {
if (mChart.isAdjustXLegendEnabled())
mChart.setAdjustXLegend(false);
else
mChart.setAdjustXLegend(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title" + System.currentTimeMillis(), "");
break;
}
}
return true;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
xVals.add((i) + "");
}
ArrayList<Series> yVals = new ArrayList<Series>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress() + 1);
float val = (float) (Math.random() * mult * 0.1) + 3;// + (float) ((mult * 0.1) / 10);
yVals.add(new Series(val, i, 0));
}
tvX.setText("" + (mSeekBarX.getProgress() + 1));
tvY.setText("" + (mSeekBarY.getProgress() / 10));
ChartData data = new ChartData(xVals, yVals);
mChart.setData(data);
mChart.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}

View file

@ -1,5 +1,7 @@
package com.example.mpchartexample;
import java.util.ArrayList;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
@ -11,173 +13,172 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.github.mikephil.charting.ChartData;
import com.github.mikephil.charting.LineChart;
import com.github.mikephil.charting.LineSeries;
import com.github.mikephil.charting.Series;
import java.util.ArrayList;
public class LineChartActivity extends Activity implements OnSeekBarChangeListener {
private LineChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
private LineChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_linechart);
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarX.setOnSeekBarChangeListener(this);
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
mSeekBarY.setOnSeekBarChangeListener(this);
mChart = (LineChart) findViewById(R.id.chart1);
// mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.LIBERTY_COLORS)));
// mChart.setDrawFilled(true);
// mChart.setRoundedYLegend(false);
// mChart.setStartAtZero(true);
mChart.setDrawYValues(false);
mChart.setLineWidth(4f);
mChart.setCircleSize(4f);
// mChart.setSpacePercent(20, 10);
mChart.setYLegendCount(6);
mChart.setTouchEnabled(true);
mChart.setHighlightEnabled(true);
// mChart.highlightValues(new int[] {2, 6});
mChart.setDragEnabled(true);
mChart.setTouchEnabled(true);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_linechart);
TextView textView = new TextView(this);
textView.setVisibility(View.VISIBLE);
textView.setBackgroundColor(Color.WHITE);
textView.setPadding(15, 15, 15, 15);
textView.setText("Marker View");
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
mChart.setDrawMarkerView(true);
mChart.setMarkerView(textView);
mSeekBarX.setProgress(45);
mSeekBarY.setProgress(100);
}
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarX.setOnSeekBarChangeListener(this);
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.line, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleRound: {
if (mChart.isYLegendRounded())
mChart.setRoundedYLegend(false);
else
mChart.setRoundedYLegend(true);
mChart.invalidate();
break;
}
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlight: {
if (mChart.isHighlightEnabled())
mChart.setHighlightEnabled(false);
else
mChart.setHighlightEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleFilled: {
if (mChart.isDrawFilledEnabled())
mChart.setDrawFilled(false);
else
mChart.setDrawFilled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleCircles: {
if (mChart.isDrawCirclesEnabled())
mChart.setDrawCircles(false);
else
mChart.setDrawCircles(true);
mChart.invalidate();
break;
}
case R.id.actionToggleStartzero: {
if (mChart.isStartAtZeroEnabled())
mChart.setStartAtZero(false);
else
mChart.setStartAtZero(true);
mChart.invalidate();
break;
}
case R.id.actionToggleAdjustXLegend: {
if (mChart.isAdjustXLegendEnabled())
mChart.setAdjustXLegend(false);
else
mChart.setAdjustXLegend(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title"+System.currentTimeMillis(), "");
break;
}
}
return true;
}
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
mSeekBarY.setOnSeekBarChangeListener(this);
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
xVals.add((i)+"");
}
mChart = (LineChart) findViewById(R.id.chart1);
// mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.LIBERTY_COLORS)));
ArrayList<Series> yVals = new ArrayList<Series>();
// mChart.setDrawFilled(true);
// mChart.setRoundedYLegend(false);
// mChart.setStartAtZero(true);
mChart.setDrawYValues(false);
mChart.setLineWidth(4f);
mChart.setCircleSize(4f);
// mChart.setSpacePercent(20, 10);
mChart.setYLegendCount(6);
mChart.setTouchEnabled(true);
mChart.setHighlightEnabled(true);
// mChart.highlightValues(new int[] {2, 6});
mChart.setDragEnabled(true);
mChart.setTouchEnabled(true);
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress()+1);
float val = (float) (Math.random() * mult * 0.1) + 3;// + (float) ((mult * 0.1) / 10);
yVals.add(new LineSeries(val, 0, i));
}
tvX.setText(""+ (mSeekBarX.getProgress() + 1));
tvY.setText(""+ (mSeekBarY.getProgress() / 10));
TextView textView = new TextView(this);
textView.setVisibility(View.VISIBLE);
textView.setBackgroundColor(Color.WHITE);
textView.setPadding(15, 15, 15, 15);
textView.setText("Marker View");
mChart.setData(xVals, yVals);
mChart.invalidate();
}
mChart.setDrawMarkerView(true);
mChart.setMarkerView(textView);
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
mSeekBarX.setProgress(45);
mSeekBarY.setProgress(100);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.line, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleRound: {
if (mChart.isYLegendRounded())
mChart.setRoundedYLegend(false);
else
mChart.setRoundedYLegend(true);
mChart.invalidate();
break;
}
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlight: {
if (mChart.isHighlightEnabled())
mChart.setHighlightEnabled(false);
else
mChart.setHighlightEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleFilled: {
if (mChart.isDrawFilledEnabled())
mChart.setDrawFilled(false);
else
mChart.setDrawFilled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleCircles: {
if (mChart.isDrawCirclesEnabled())
mChart.setDrawCircles(false);
else
mChart.setDrawCircles(true);
mChart.invalidate();
break;
}
case R.id.actionToggleStartzero: {
if (mChart.isStartAtZeroEnabled())
mChart.setStartAtZero(false);
else
mChart.setStartAtZero(true);
mChart.invalidate();
break;
}
case R.id.actionToggleAdjustXLegend: {
if (mChart.isAdjustXLegendEnabled())
mChart.setAdjustXLegend(false);
else
mChart.setAdjustXLegend(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title" + System.currentTimeMillis(), "");
break;
}
}
return true;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
xVals.add((i) + "");
}
ArrayList<Series> yVals = new ArrayList<Series>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress() + 1);
float val = (float) (Math.random() * mult * 0.1) + 3;// + (float) ((mult * 0.1) / 10);
yVals.add(new Series(val, 0, i));
}
tvX.setText("" + (mSeekBarX.getProgress() + 1));
tvY.setText("" + (mSeekBarY.getProgress() / 10));
ChartData data = new ChartData(xVals, yVals);
mChart.setData(data);
mChart.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}

View file

@ -1,5 +1,7 @@
package com.example.mpchartexample;
import java.util.ArrayList;
import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
@ -11,173 +13,189 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.github.mikephil.charting.Approximator;
import com.github.mikephil.charting.ChartData;
import com.github.mikephil.charting.LineChart;
import com.github.mikephil.charting.LineSeries;
import com.github.mikephil.charting.Point;
import com.github.mikephil.charting.Series;
import java.util.ArrayList;
import com.github.mikephil.charting.Approximator.ApproximatorType;
public class MultiLineChartActivity extends Activity implements OnSeekBarChangeListener {
private LineChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
private LineChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_linechart);
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarX.setOnSeekBarChangeListener(this);
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
mSeekBarY.setOnSeekBarChangeListener(this);
mChart = (LineChart) findViewById(R.id.chart1);
// mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.LIBERTY_COLORS)));
// mChart.setDrawFilled(true);
// mChart.setRoundedYLegend(false);
// mChart.setStartAtZero(true);
mChart.setDrawYValues(false);
mChart.setLineWidth(4f);
mChart.setCircleSize(4f);
// mChart.setSpacePercent(20, 10);
mChart.setYLegendCount(6);
mChart.setTouchEnabled(true);
mChart.setHighlightEnabled(true);
// mChart.highlightValues(new int[] {2, 6});
mChart.setDragEnabled(true);
mChart.setTouchEnabled(true);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_linechart);
TextView textView = new TextView(this);
textView.setVisibility(View.VISIBLE);
textView.setBackgroundColor(Color.WHITE);
textView.setPadding(15, 15, 15, 15);
textView.setText("Marker View");
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
mChart.setDrawMarkerView(true);
mChart.setMarkerView(textView);
mSeekBarX.setProgress(45);
mSeekBarY.setProgress(100);
}
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarX.setOnSeekBarChangeListener(this);
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.line, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleRound: {
if (mChart.isYLegendRounded())
mChart.setRoundedYLegend(false);
else
mChart.setRoundedYLegend(true);
mChart.invalidate();
break;
}
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlight: {
if (mChart.isHighlightEnabled())
mChart.setHighlightEnabled(false);
else
mChart.setHighlightEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleFilled: {
if (mChart.isDrawFilledEnabled())
mChart.setDrawFilled(false);
else
mChart.setDrawFilled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleCircles: {
if (mChart.isDrawCirclesEnabled())
mChart.setDrawCircles(false);
else
mChart.setDrawCircles(true);
mChart.invalidate();
break;
}
case R.id.actionToggleStartzero: {
if (mChart.isStartAtZeroEnabled())
mChart.setStartAtZero(false);
else
mChart.setStartAtZero(true);
mChart.invalidate();
break;
}
case R.id.actionToggleAdjustXLegend: {
if (mChart.isAdjustXLegendEnabled())
mChart.setAdjustXLegend(false);
else
mChart.setAdjustXLegend(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title"+System.currentTimeMillis(), "");
break;
}
}
return true;
}
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
mSeekBarY.setOnSeekBarChangeListener(this);
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
xVals.add((i)+"");
}
mChart = (LineChart) findViewById(R.id.chart1);
// mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.LIBERTY_COLORS)));
ArrayList<Series> yVals = new ArrayList<Series>();
// mChart.setDrawFilled(true);
// mChart.setRoundedYLegend(false);
// mChart.setStartAtZero(true);
mChart.setDrawYValues(false);
mChart.setLineWidth(4f);
mChart.setCircleSize(4f);
// mChart.setSpacePercent(20, 10);
mChart.setYLegendCount(6);
mChart.setTouchEnabled(true);
mChart.setHighlightEnabled(true);
// mChart.highlightValues(new int[] {2, 6});
mChart.setDragEnabled(true);
mChart.setTouchEnabled(true);
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress()+1);
float val = (float) (Math.random() * mult * 0.1) + 3;// + (float) ((mult * 0.1) / 10);
yVals.add(new LineSeries(val, 0, i));
}
tvX.setText(""+ (mSeekBarX.getProgress() + 1));
tvY.setText(""+ (mSeekBarY.getProgress() / 10));
TextView textView = new TextView(this);
textView.setVisibility(View.VISIBLE);
textView.setBackgroundColor(Color.WHITE);
textView.setPadding(15, 15, 15, 15);
textView.setText("Marker View");
mChart.setData(xVals, yVals);
mChart.invalidate();
}
mChart.setDrawMarkerView(true);
mChart.setMarkerView(textView);
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
mSeekBarX.setProgress(45);
mSeekBarY.setProgress(100);
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.line, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleRound: {
if (mChart.isYLegendRounded())
mChart.setRoundedYLegend(false);
else
mChart.setRoundedYLegend(true);
mChart.invalidate();
break;
}
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
mChart.invalidate();
break;
}
case R.id.actionToggleHighlight: {
if (mChart.isHighlightEnabled())
mChart.setHighlightEnabled(false);
else
mChart.setHighlightEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleFilled: {
if (mChart.isDrawFilledEnabled())
mChart.setDrawFilled(false);
else
mChart.setDrawFilled(true);
mChart.invalidate();
break;
}
case R.id.actionToggleCircles: {
if (mChart.isDrawCirclesEnabled())
mChart.setDrawCircles(false);
else
mChart.setDrawCircles(true);
mChart.invalidate();
break;
}
case R.id.actionToggleStartzero: {
if (mChart.isStartAtZeroEnabled())
mChart.setStartAtZero(false);
else
mChart.setStartAtZero(true);
mChart.invalidate();
break;
}
case R.id.actionToggleAdjustXLegend: {
if (mChart.isAdjustXLegendEnabled())
mChart.setAdjustXLegend(false);
else
mChart.setAdjustXLegend(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title" + System.currentTimeMillis(), "");
break;
}
}
return true;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
xVals.add((i) + "");
}
ArrayList<Series> yVals = new ArrayList<Series>();
Approximator approximator = new Approximator(ApproximatorType.DOUGLAS_PEUCKER);
for (int z = 0; z < 1; z++) {
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress() + 1);
float val = (float) (Math.random() * mult * 0.1) + 3;// + (float) ((mult * 0.1) / 10);
yVals.add(new Series(val, z, i));
}
}
ArrayList<Series> filtered = approximator.filter(yVals);
for (int i = 0; i < filtered.size(); i++) {
filtered.get(i).setType(1);
}
// yVals.addAll(filtered);
// for (int z = 0; z < 5; z++) {
// for (int i = 0; i < mSeekBarX.getProgress(); i++) {
// float mult = (mSeekBarY.getProgress() + 1);
// float val = (float) (Math.random() * mult * 0.1) + 3;// + (float) ((mult * 0.1) / 10);
// yVals.add(new Series(val, z, i));
// }
// }
tvX.setText("" + (mSeekBarX.getProgress() + 1));
tvY.setText("" + (mSeekBarY.getProgress() / 10));
ChartData data = new ChartData(xVals, filtered);
mChart.setData(data);
mChart.invalidate();
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
}
}

View file

@ -1,5 +1,7 @@
package com.example.mpchartexample;
import java.util.ArrayList;
import android.app.Activity;
import android.os.Bundle;
import android.util.Log;
@ -10,166 +12,166 @@ import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TextView;
import com.github.mikephil.charting.ChartData;
import com.github.mikephil.charting.ColorTemplate;
import com.github.mikephil.charting.OnChartValueSelectedListener;
import com.github.mikephil.charting.PieChart;
import com.github.mikephil.charting.PieSeries;
import com.github.mikephil.charting.Series;
import java.util.ArrayList;
public class PieChartActivity extends Activity implements OnSeekBarChangeListener, OnChartValueSelectedListener {
private PieChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
private PieChart mChart;
private SeekBar mSeekBarX, mSeekBarY;
private TextView tvX, tvY;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_piechart);
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
mSeekBarX.setOnSeekBarChangeListener(this);
mSeekBarY.setOnSeekBarChangeListener(this);
mChart = (PieChart) findViewById(R.id.chart1);
mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.COLORFUL_COLORS)));
mChart.setDrawYValues(true);
mChart.setDrawCenterText(true);
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
setContentView(R.layout.activity_piechart);
mChart.setDescription("This is a description.");
mChart.setDrawHoleEnabled(true);
mChart.setDrawXValues(true);
mChart.setTouchEnabled(true);
mChart.setUsePercentValues(false);
mChart.setOnChartValueSelectedListener(this);
mSeekBarX.setProgress(5);
mSeekBarY.setProgress(100);
// float diameter = mChart.getDiameter();
// float radius = mChart.getRadius();
//
// Log.i("Piechart", "diameter: " + diameter + ", radius: " + radius);
}
tvX = (TextView) findViewById(R.id.tvXMax);
tvY = (TextView) findViewById(R.id.tvYMax);
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.pie, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
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);
else
mChart.setDrawHoleEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionDrawCenter: {
if (mChart.isDrawCenterTextEnabled())
mChart.setDrawCenterText(false);
else
mChart.setDrawCenterText(true);
mChart.invalidate();
break;
}
case R.id.actionToggleXVals: {
if (mChart.isDrawXValuesEnabled())
mChart.setDrawXValues(false);
else
mChart.setDrawXValues(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title"+System.currentTimeMillis(), "");
break;
}
}
return true;
}
mSeekBarX = (SeekBar) findViewById(R.id.seekBar1);
mSeekBarY = (SeekBar) findViewById(R.id.seekBar2);
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<Series> yVals = new ArrayList<Series>();
mSeekBarX.setOnSeekBarChangeListener(this);
mSeekBarY.setOnSeekBarChangeListener(this);
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress());
float val = (float) (Math.random() * mult) + mult / 5;// + (float) ((mult * 0.1) / 10);
yVals.add(new PieSeries(val));
}
tvX.setText(""+ (mSeekBarX.getProgress()));
tvY.setText(""+ (mSeekBarY.getProgress()));
mChart = (PieChart) findViewById(R.id.chart1);
mChart.setColorTemplate(new ColorTemplate(ColorTemplate.getColors(this, ColorTemplate.COLORFUL_COLORS)));
ArrayList<String> xVals = new ArrayList<String>();
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());
// immediately unselect
// mChart.highlightValues(null);
}
mChart.setDrawYValues(true);
mChart.setDrawCenterText(true);
@Override
public void onNothingSelected() {
Log.i("PieChart", "nothing selected");
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
mChart.setDescription("This is a description.");
mChart.setDrawHoleEnabled(true);
mChart.setDrawXValues(true);
mChart.setTouchEnabled(true);
mChart.setUsePercentValues(false);
mChart.setOnChartValueSelectedListener(this);
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
mSeekBarX.setProgress(5);
mSeekBarY.setProgress(100);
// float diameter = mChart.getDiameter();
// float radius = mChart.getRadius();
//
// Log.i("Piechart", "diameter: " + diameter + ", radius: " + radius);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.pie, menu);
return true;
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.actionToggleValues: {
if (mChart.isDrawYValuesEnabled())
mChart.setDrawYValues(false);
else
mChart.setDrawYValues(true);
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);
else
mChart.setDrawHoleEnabled(true);
mChart.invalidate();
break;
}
case R.id.actionDrawCenter: {
if (mChart.isDrawCenterTextEnabled())
mChart.setDrawCenterText(false);
else
mChart.setDrawCenterText(true);
mChart.invalidate();
break;
}
case R.id.actionToggleXVals: {
if (mChart.isDrawXValuesEnabled())
mChart.setDrawXValues(false);
else
mChart.setDrawXValues(true);
mChart.invalidate();
break;
}
case R.id.actionSave: {
// mChart.saveToGallery("title"+System.currentTimeMillis());
mChart.saveToPath("title" + System.currentTimeMillis(), "");
break;
}
}
return true;
}
@Override
public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
ArrayList<Series> yVals = new ArrayList<Series>();
for (int i = 0; i < mSeekBarX.getProgress(); i++) {
float mult = (mSeekBarY.getProgress());
float val = (float) (Math.random() * mult) + mult / 5;// + (float) ((mult * 0.1) / 10);
yVals.add(new Series(val, i, 0));
}
tvX.setText("" + (mSeekBarX.getProgress()));
tvY.setText("" + (mSeekBarY.getProgress()));
ArrayList<String> xVals = new ArrayList<String>();
for (int i = 0; i < yVals.size(); i++)
xVals.add("Text" + (i + 1));
ChartData data = new ChartData(xVals, yVals);
mChart.setData(data);
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());
// immediately unselect
// mChart.highlightValues(null);
}
@Override
public void onNothingSelected() {
Log.i("PieChart", "nothing selected");
}
@Override
public void onStartTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
@Override
public void onStopTrackingTouch(SeekBar seekBar) {
// TODO Auto-generated method stub
}
}

View file

@ -0,0 +1,142 @@
package com.github.mikephil.charting;
import java.util.ArrayList;
/**
* Implemented according to Wiki-Pseudocode {@link} http://en.wikipedia.org/wiki/RamerÐDouglasÐPeucker_algorithm
*
* @author Philipp Baldauf & Phliipp Jahoda
*/
public class Approximator {
private ApproximatorType type = ApproximatorType.NONE;
public enum ApproximatorType {
NONE, DOUGLAS_PEUCKER
}
private boolean[] keep;
public Approximator(ApproximatorType type) {
this.type = type;
}
public ArrayList<Series> filter(ArrayList<Series> points) {
keep = new boolean[points.size()];
switch (type) {
case DOUGLAS_PEUCKER:
return reduceWithDouglasPeuker(points, 1);
case NONE:
return null;
default:
return null;
}
}
private ArrayList<Series> reduceWithDouglasPeuker(ArrayList<Series> series, double epsilon) {
// if a shape has 2 or less points it cannot be reduced
if (epsilon <= 0 || series.size() < 3) {
return null;
}
// first and last always stay
keep[0] = true;
keep[series.size() - 1] = true;
// first and last series are entry point to recursion
algorithmDouglasPeucker(series, epsilon, 0, series.size() - 1);
// create a new array with series, only take the kept ones
ArrayList<Series> reducedSeries = new ArrayList<Series>();
for (int i = 0; i < series.size(); i++) {
if (keep[i]) {
Series curSeries = series.get(i);
reducedSeries.add(new Series(curSeries.getVal(), curSeries.getType(), curSeries.getXIndex()));
}
}
return reducedSeries;
}
/**
* apply the Douglas-Peucker-Reduction to an ArrayList of Series with a given epsilon (tolerance)
*
* @param series
* @param epsilon
* as y-value
* @param start
* @param end
*/
private void algorithmDouglasPeucker(ArrayList<Series> series, double epsilon, int start, int end) {
if (end <= start + 1) {
// recursion finished
return;
}
// find the greatest distance between start and endpoint
int maxDistIndex = 0;
double distMax = 0;
Series firstSeries = series.get(start);
Series lastSeries = series.get(end);
for (int i = start + 1; i < end; i++) {
double dist = pointToLineDistance(firstSeries, lastSeries, series.get(i));
// keep the point with the greatest distance
if (dist > distMax) {
distMax = dist;
maxDistIndex = i;
}
}
if (distMax > epsilon) {
// keep max dist point
keep[maxDistIndex] = true;
// recursive call
algorithmDouglasPeucker(series, epsilon, start, maxDistIndex);
algorithmDouglasPeucker(series, epsilon, maxDistIndex, end);
}
}
/**
* calculate the distance between a line between two series and a series (point)
*
* @param startSeries
* @param endSeries
* @param seriesToInspect
* @return
*/
public double pointToLineDistance(Series startSeries, Series endSeries, Series seriesToInspect) {
double normalLength = Math.sqrt((endSeries.getXIndex() - startSeries.getXIndex())
* (endSeries.getXIndex() - startSeries.getXIndex()) + (endSeries.getVal() - startSeries.getVal())
* (endSeries.getVal() - startSeries.getVal()));
return Math.abs((seriesToInspect.getXIndex() - startSeries.getXIndex())
* (endSeries.getVal() - startSeries.getVal()) - (seriesToInspect.getVal() - startSeries.getVal())
* (endSeries.getXIndex() - startSeries.getXIndex()))
/ normalLength;
}
// /**
// * calculate the distance between a line between two series and a series (point)
// *
// * @param seriesToInspect
// * @param startSeries
// * @param endSeries
// * @return
// */
// private static double shortestDistToSegment(Series seriesToInspect, Series startSeries, Series endSeries) {
// double area = Math.abs((startSeries.getVal() * endSeries.getXIndex() + endSeries.getVal()
// * seriesToInspect.getXIndex() + seriesToInspect.getVal() * startSeries.getXIndex() - endSeries.getVal()
// * startSeries.getXIndex() - seriesToInspect.getVal() * endSeries.getXIndex() - startSeries.getVal()
// * seriesToInspect.getXIndex()) / 2.0);
//
// double bottom = Math.hypot(startSeries.getVal() - endSeries.getVal(),
// startSeries.getXIndex() - endSeries.getXIndex());
//
// return (area / bottom * 2.0);
// }
}

View file

@ -1,4 +1,3 @@
package com.github.mikephil.charting;
import android.content.Context;
@ -14,416 +13,410 @@ import java.util.ArrayList;
public class BarChart extends BarLineChartBase {
/** space indicator between the bars 0.1f == 10 % */
private float mBarSpace = 0.1f;
/** space indicator between the bars 0.1f == 10 % */
private float mBarSpace = 0.1f;
/** indicates the angle of the 3d effect */
private float mSkew = 0.3f;
/** indicates the angle of the 3d effect */
private float mSkew = 0.3f;
/** indicates how much the 3d effect goes back */
private float mDepth = 0.3f;
/** indicates how much the 3d effect goes back */
private float mDepth = 0.3f;
/** flag the enables or disables 3d bars */
private boolean m3DEnabled = true;
/** flag that enables or disables the highlighting arrow */
private boolean mDrawHighlightArrow = true;
/** flag the enables or disables 3d bars */
private boolean m3DEnabled = true;
public BarChart(Context context) {
super(context);
}
/** flag that enables or disables the highlighting arrow */
private boolean mDrawHighlightArrow = true;
public BarChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public BarChart(Context context) {
super(context);
}
public BarChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public BarChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
@Override
protected void init() {
super.init();
public BarChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setStyle(Paint.Style.FILL);
mHighlightPaint.setColor(Color.rgb(0, 0, 0));
// set alpha after color
mHighlightPaint.setAlpha(120);
}
/** array that holds all the colors for the top 3D effect */
private int[] mTopColors;
/** array that holds all the colors for the side 3D effect */
private int[] mSideColors;
@Override
protected void prepareDataPaints(ColorTemplate ct) {
// prepare the paints
mDrawPaints = new Paint[ct.getColors().size()];
for (int i = 0; i < ct.getColors().size(); i++) {
mDrawPaints[i] = new Paint(Paint.ANTI_ALIAS_FLAG);
mDrawPaints[i].setStyle(Style.FILL);
mDrawPaints[i].setColor(ct.getColors().get(i));
}
// generate the colors for the 3D effect
mTopColors = new int[mDrawPaints.length];
mSideColors = new int[mDrawPaints.length];
float[] hsv = new float[3];
for (int i = 0; i < mSideColors.length; i++) {
// extract the color
int c = mDrawPaints[i].getColor();
Color.colorToHSV(c, hsv); // convert to hsv
// make brighter
hsv[1] = hsv[1] - 0.1f; // less saturation
hsv[2] = hsv[2] + 0.1f; // more brightness
// convert back
c = Color.HSVToColor(hsv);
// assign
mTopColors[i] = c;
// get color again
c = mDrawPaints[i].getColor();
// convert
Color.colorToHSV(c, hsv);
// make darker
hsv[1] = hsv[1] + 0.1f; // more saturation
hsv[2] = hsv[2] - 0.1f; // less brightness
// reassing
c = Color.HSVToColor(hsv);
mSideColors[i] = c;
}
}
@Override
protected void init() {
super.init();
@Override
protected void calcMinMax() {
super.calcMinMax();
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setStyle(Paint.Style.FILL);
mHighlightPaint.setColor(Color.rgb(0, 0, 0));
// set alpha after color
mHighlightPaint.setAlpha(120);
}
// increase deltax by 1 because the bars have a width of 1
mDeltaX++;
}
/** array that holds all the colors for the top 3D effect */
private int[] mTopColors;
@Override
protected void drawHighlights() {
// if there are values to highlight and highlighnting is enabled, do it
if (mHighlightEnabled && valuesToHighlight()) {
// distance between highlight arrow and bar
float offsetY = mDeltaY * 0.04f;
for (int i = 0; i < mIndicesToHightlight.length; i++) {
int index = mIndicesToHightlight[i];
// check outofbounds
if (index < mYVals.size() && index >= 0) {
mHighlightPaint.setAlpha(120);
float y = mYVals.get(index).getVal();
float left = index + mBarSpace / 2f;
float right = index + 1f - mBarSpace / 2f;
float top = y >= 0 ? y : 0;
float bottom = y <= 0 ? y : 0;
/** array that holds all the colors for the side 3D effect */
private int[] mSideColors;
RectF highlight = new RectF(left, top, right, bottom);
transformRect(highlight);
mDrawCanvas.drawRect(highlight, mHighlightPaint);
if(mDrawHighlightArrow) {
mHighlightPaint.setAlpha(200);
Path arrow = new Path();
arrow.moveTo(index + 0.5f, y + offsetY * 0.3f);
arrow.lineTo(index + 0.2f, y + offsetY);
arrow.lineTo(index + 0.8f, y + offsetY);
transformPath(arrow);
mDrawCanvas.drawPath(arrow, mHighlightPaint);
}
@Override
protected void prepareDataPaints(ColorTemplate ct) {
// float[] pts = new float[] {
// index + 0.5f, mYChartMax, index + 0.5f, mYChartMin,
// 0, mYVals.get(index), mDeltaX, mYVals.get(index)
// };
//
// transformPointArray(pts);
// // draw the highlight lines
// mDrawCanvas.drawLines(pts, mHighlightPaint);
}
}
}
}
// prepare the paints
mDrawPaints = new Paint[ct.getColors().size()];
private RectF mBarRect = new RectF();
for (int i = 0; i < ct.getColors().size(); i++) {
mDrawPaints[i] = new Paint(Paint.ANTI_ALIAS_FLAG);
mDrawPaints[i].setStyle(Style.FILL);
mDrawPaints[i].setColor(ct.getColors().get(i));
}
@Override
protected void drawData() {
// generate the colors for the 3D effect
mTopColors = new int[mDrawPaints.length];
mSideColors = new int[mDrawPaints.length];
ArrayList<Path> topPaths = new ArrayList<Path>();
ArrayList<Path> sidePaths = new ArrayList<Path>();
float[] hsv = new float[3];
if (m3DEnabled) {
for (int i = 0; i < mSideColors.length; i++) {
float[] pts = new float[] {
0f, 0f, 1f, 0f
};
// extract the color
int c = mDrawPaints[i].getColor();
Color.colorToHSV(c, hsv); // convert to hsv
// calculate the depth depending on scale
// make brighter
hsv[1] = hsv[1] - 0.1f; // less saturation
hsv[2] = hsv[2] + 0.1f; // more brightness
transformPointArray(pts);
// convert back
c = Color.HSVToColor(hsv);
pts[3] = pts[2] - pts[0];
pts[2] = 0f;
pts[1] = 0f;
pts[0] = 0f;
// assign
mTopColors[i] = c;
Matrix invert = new Matrix();
mMatrixOffset.invert(invert);
invert.mapPoints(pts);
mMatrixTouch.invert(invert);
invert.mapPoints(pts);
mMatrixValueToPx.invert(invert);
invert.mapPoints(pts);
float depth = Math.abs(pts[3] - pts[1]) * mDepth;
for (int i = 0; i < mYVals.size(); i++) {
float y = mYVals.get(i).getVal();
float left = i + mBarSpace / 2f;
float right = i + 1f - mBarSpace / 2f;
float top = y >= 0 ? y : 0;
// create the 3D effect paths for the top and side
Path topPath = new Path();
topPath.moveTo(left, top);
topPath.lineTo(left + mSkew, top + depth);
topPath.lineTo(right + mSkew, top + depth);
topPath.lineTo(right, top);
topPaths.add(topPath);
Path sidePath = new Path();
sidePath.moveTo(right, top);
sidePath.lineTo(right + mSkew, top + depth);
sidePath.lineTo(right + mSkew, depth);
sidePath.lineTo(right, 0);
sidePaths.add(sidePath);
}
transformPaths(topPaths);
transformPaths(sidePaths);
}
// do the drawing
for (int i = 0; i < mYVals.size(); i++) {
Paint paint = mDrawPaints[i % mDrawPaints.length];
float y = mYVals.get(i).getVal();
float left = i + mBarSpace / 2f;
float right = i + 1f - mBarSpace / 2f;
float top = y >= 0 ? y : 0;
float bottom = y <= 0 ? y : 0;
mBarRect.set(left, top, right, bottom);
transformRect(mBarRect);
mDrawCanvas.drawRect(mBarRect, paint);
if (m3DEnabled) {
int c = paint.getColor();
paint.setColor(mTopColors[i % mTopColors.length]);
mDrawCanvas.drawPath(topPaths.get(i), paint);
paint.setColor(mSideColors[i % mSideColors.length]);
mDrawCanvas.drawPath(sidePaths.get(i), paint);
paint.setColor(c);
}
}
}
@Override
protected void drawValues() {
// if values are drawn
if (mDrawYValues && mYVals.size() < mMaxVisibleCount * mScaleX) {
float[] valuePoints = new float[mYVals.size() * 2];
for (int i = 0; i < valuePoints.length; i += 2) {
valuePoints[i] = i / 2 + 0.5f; // add 0.5f too keep the values
// centered on top of the bars
valuePoints[i + 1] = mYVals.get(i / 2).getVal();
}
transformPointArray(valuePoints);
for (int i = 0; i < valuePoints.length; i += 2) {
if(mDrawUnitInChart) {
mDrawCanvas.drawText(
mFormatValue.format(mYVals.get(i / 2).getVal()) + mUnit,
valuePoints[i], valuePoints[i + 1] - 12, mValuePaint);
} else {
mDrawCanvas.drawText(
mFormatValue.format(mYVals.get(i / 2).getVal()),
valuePoints[i], valuePoints[i + 1] - 12, mValuePaint);
}
}
}
}
/**
* sets the skew (default 0.3f), the skew indicates how much the 3D effect
* of the chart is turned to the right
*
* @param skew
*/
public void setSkew(float skew) {
this.mSkew = skew;
}
/**
* returns the skew value that indicates how much the 3D effect is turned to
* the right
*
* @return
*/
public float getSkew() {
return mSkew;
}
/**
* set the depth of the chart (default 0.3f), the depth indicates how much
* the 3D effect of the chart goes back
*
* @param depth
*/
public void setDepth(float depth) {
this.mDepth = depth;
}
/**
* returhs the depth, which indicates how much the 3D effect goes back
*
* @return
*/
public float getDepth() {
return mDepth;
}
/**
* returns the space between bars in percent of the whole width of one value
*
* @return
*/
public float getBarSpace() {
return mBarSpace * 100f;
}
/**
* sets the space between the bars in percent of the total bar width
*
* @param percent
*/
public void setBarSpace(float percent) {
mBarSpace = percent / 100f;
}
/**
* if enabled, chart will be drawn in 3d
*
* @param enabled
*/
public void set3DEnabled(boolean enabled) {
this.m3DEnabled = enabled;
}
/**
* returns true if 3d bars is enabled, false if not
*
* @return
*/
public boolean is3DEnabled() {
return m3DEnabled;
}
/**
* returns the top colors that define the color of the top 3D effect path
*
* @return
*/
public int[] getTopColors() {
return mTopColors;
}
/**
* returns the side colors that define the color of the side 3D effect path
*
* @return
*/
public int[] getSideColors() {
return mSideColors;
}
/**
* set this to true to draw the highlightning arrow
* @param enabled
*/
public void setDrawHighlightArrow(boolean enabled) {
mDrawHighlightArrow = enabled;
}
/**
* returns true if drawing the highlighting arrow is enabled, false if not
* @return
*/
public boolean isDrawHighlightArrowEnabled() {
return mDrawHighlightArrow;
}
@Override
public void setPaint(Paint p, int which) {
super.setPaint(p, which);
switch (which) {
case PAINT_HIGHLIGHT_BAR:
mHighlightPaint = p;
break;
}
}
@Override
protected void drawAdditional() {
}
// get color again
c = mDrawPaints[i].getColor();
// convert
Color.colorToHSV(c, hsv);
// make darker
hsv[1] = hsv[1] + 0.1f; // more saturation
hsv[2] = hsv[2] - 0.1f; // less brightness
// reassing
c = Color.HSVToColor(hsv);
mSideColors[i] = c;
}
}
@Override
protected void calcMinMax() {
super.calcMinMax();
// increase deltax by 1 because the bars have a width of 1
mDeltaX++;
}
@Override
protected void drawHighlights() {
// if there are values to highlight and highlighnting is enabled, do it
if (mHighlightEnabled && valuesToHighlight()) {
// distance between highlight arrow and bar
float offsetY = mDeltaY * 0.04f;
for (int i = 0; i < mIndicesToHightlight.length; i++) {
int index = mIndicesToHightlight[i];
// check outofbounds
if (index < mData.getYValSize() && index >= 0) {
mHighlightPaint.setAlpha(120);
float y = mData.getYVals().get(index).getVal();
float left = index + mBarSpace / 2f;
float right = index + 1f - mBarSpace / 2f;
float top = y >= 0 ? y : 0;
float bottom = y <= 0 ? y : 0;
RectF highlight = new RectF(left, top, right, bottom);
transformRect(highlight);
mDrawCanvas.drawRect(highlight, mHighlightPaint);
if (mDrawHighlightArrow) {
mHighlightPaint.setAlpha(200);
Path arrow = new Path();
arrow.moveTo(index + 0.5f, y + offsetY * 0.3f);
arrow.lineTo(index + 0.2f, y + offsetY);
arrow.lineTo(index + 0.8f, y + offsetY);
transformPath(arrow);
mDrawCanvas.drawPath(arrow, mHighlightPaint);
}
// float[] pts = new float[] {
// index + 0.5f, mYChartMax, index + 0.5f, mYChartMin,
// 0, mYVals.get(index), mDeltaX, mYVals.get(index)
// };
//
// transformPointArray(pts);
// // draw the highlight lines
// mDrawCanvas.drawLines(pts, mHighlightPaint);
}
}
}
}
private RectF mBarRect = new RectF();
@Override
protected void drawData() {
ArrayList<Path> topPaths = new ArrayList<Path>();
ArrayList<Path> sidePaths = new ArrayList<Path>();
if (m3DEnabled) {
float[] pts = new float[] { 0f, 0f, 1f, 0f };
// calculate the depth depending on scale
transformPointArray(pts);
pts[3] = pts[2] - pts[0];
pts[2] = 0f;
pts[1] = 0f;
pts[0] = 0f;
Matrix invert = new Matrix();
mMatrixOffset.invert(invert);
invert.mapPoints(pts);
mMatrixTouch.invert(invert);
invert.mapPoints(pts);
mMatrixValueToPx.invert(invert);
invert.mapPoints(pts);
float depth = Math.abs(pts[3] - pts[1]) * mDepth;
for (int i = 0; i < mData.getYValSize(); i++) {
float y = mData.getYVals().get(i).getVal();
float left = i + mBarSpace / 2f;
float right = i + 1f - mBarSpace / 2f;
float top = y >= 0 ? y : 0;
// create the 3D effect paths for the top and side
Path topPath = new Path();
topPath.moveTo(left, top);
topPath.lineTo(left + mSkew, top + depth);
topPath.lineTo(right + mSkew, top + depth);
topPath.lineTo(right, top);
topPaths.add(topPath);
Path sidePath = new Path();
sidePath.moveTo(right, top);
sidePath.lineTo(right + mSkew, top + depth);
sidePath.lineTo(right + mSkew, depth);
sidePath.lineTo(right, 0);
sidePaths.add(sidePath);
}
transformPaths(topPaths);
transformPaths(sidePaths);
}
// do the drawing
for (int i = 0; i < mData.getYValSize(); i++) {
Paint paint = mDrawPaints[i % mDrawPaints.length];
float y = mData.getYVals().get(i).getVal();
float left = i + mBarSpace / 2f;
float right = i + 1f - mBarSpace / 2f;
float top = y >= 0 ? y : 0;
float bottom = y <= 0 ? y : 0;
mBarRect.set(left, top, right, bottom);
transformRect(mBarRect);
mDrawCanvas.drawRect(mBarRect, paint);
if (m3DEnabled) {
int c = paint.getColor();
paint.setColor(mTopColors[i % mTopColors.length]);
mDrawCanvas.drawPath(topPaths.get(i), paint);
paint.setColor(mSideColors[i % mSideColors.length]);
mDrawCanvas.drawPath(sidePaths.get(i), paint);
paint.setColor(c);
}
}
}
@Override
protected void drawValues() {
// if values are drawn
if (mDrawYValues && mData.getYValSize() < mMaxVisibleCount * mScaleX) {
float[] valuePoints = new float[mData.getYValSize() * 2];
for (int i = 0; i < valuePoints.length; i += 2) {
valuePoints[i] = i / 2 + 0.5f; // add 0.5f too keep the values
// centered on top of the bars
valuePoints[i + 1] = mData.getYVals().get(i / 2).getVal();
}
transformPointArray(valuePoints);
for (int i = 0; i < valuePoints.length; i += 2) {
if (mDrawUnitInChart) {
mDrawCanvas.drawText(mFormatValue.format(mData.getYVals().get(i / 2).getVal()) + mUnit,
valuePoints[i], valuePoints[i + 1] - 12, mValuePaint);
} else {
mDrawCanvas.drawText(mFormatValue.format(mData.getYVals().get(i / 2).getVal()), valuePoints[i],
valuePoints[i + 1] - 12, mValuePaint);
}
}
}
}
/**
* sets the skew (default 0.3f), the skew indicates how much the 3D effect of the chart is turned to the right
*
* @param skew
*/
public void setSkew(float skew) {
this.mSkew = skew;
}
/**
* returns the skew value that indicates how much the 3D effect is turned to the right
*
* @return
*/
public float getSkew() {
return mSkew;
}
/**
* set the depth of the chart (default 0.3f), the depth indicates how much the 3D effect of the chart goes back
*
* @param depth
*/
public void setDepth(float depth) {
this.mDepth = depth;
}
/**
* returhs the depth, which indicates how much the 3D effect goes back
*
* @return
*/
public float getDepth() {
return mDepth;
}
/**
* returns the space between bars in percent of the whole width of one value
*
* @return
*/
public float getBarSpace() {
return mBarSpace * 100f;
}
/**
* sets the space between the bars in percent of the total bar width
*
* @param percent
*/
public void setBarSpace(float percent) {
mBarSpace = percent / 100f;
}
/**
* if enabled, chart will be drawn in 3d
*
* @param enabled
*/
public void set3DEnabled(boolean enabled) {
this.m3DEnabled = enabled;
}
/**
* returns true if 3d bars is enabled, false if not
*
* @return
*/
public boolean is3DEnabled() {
return m3DEnabled;
}
/**
* returns the top colors that define the color of the top 3D effect path
*
* @return
*/
public int[] getTopColors() {
return mTopColors;
}
/**
* returns the side colors that define the color of the side 3D effect path
*
* @return
*/
public int[] getSideColors() {
return mSideColors;
}
/**
* set this to true to draw the highlightning arrow
*
* @param enabled
*/
public void setDrawHighlightArrow(boolean enabled) {
mDrawHighlightArrow = enabled;
}
/**
* returns true if drawing the highlighting arrow is enabled, false if not
*
* @return
*/
public boolean isDrawHighlightArrowEnabled() {
return mDrawHighlightArrow;
}
@Override
public void setPaint(Paint p, int which) {
super.setPaint(p, which);
switch (which) {
case PAINT_HIGHLIGHT_BAR:
mHighlightPaint = p;
break;
}
}
@Override
protected void drawAdditional() {
}
}

View file

@ -1,10 +0,0 @@
package com.github.mikephil.charting;
public class BarSeries extends Series {
public BarSeries(float val) {
super(val);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,177 @@
package com.github.mikephil.charting;
import java.util.ArrayList;
/**
* Class that holds all relevant data that represents the chart
*
* @author Philipp
*
*/
public class ChartData {
/** maximum y-value in the y-value array */
private float mYMax = 0.0f;
/** the minimum y-value in the y-value array */
private float mYMin = 0.0f;
/** the total sum of all y-values */
private float mYValueSum = 0f;
private ArrayList<String> mXVals;
private ArrayList<Series> mYVals;
/** array that holds all the different type ids that are in the series array */
private ArrayList<Integer> mDiffTypes;
/** field that holds all the series split into their different types */
private ArrayList<ArrayList<Series>> typeSeries;
/**
* constructor for chart data
*
* @param xVals
* must be at least as long as the longest series array of one type
* @param yVals
* all y series values
*/
public ChartData(ArrayList<String> xVals, ArrayList<Series> yVals) {
this.mXVals = xVals;
this.mYVals = yVals;
calcTypes();
calcMinMax();
calcYValueSum();
calcTypeSeries();
for (int i = 0; i < typeSeries.size(); i++) {
if (typeSeries.get(i).size() > xVals.size()) {
throw new IllegalArgumentException("x values are smaller than the largest y series array of one type");
}
}
}
/**
* calculates all different types that occur in the series and stores them for fast access
*/
private void calcTypes() {
mDiffTypes = new ArrayList<Integer>();
for (int i = 0; i < mYVals.size(); i++) {
int type = mYVals.get(i).getType();
if (!alreadyCounted(mDiffTypes, type)) {
mDiffTypes.add(type);
}
}
}
/**
* calc minimum and maximum y value
*/
private void calcMinMax() {
mYMin = mYVals.get(0).getVal();
mYMax = mYVals.get(0).getVal();
for (int i = 0; i < mYVals.size(); i++) {
if (mYVals.get(i).getVal() < mYMin)
mYMin = mYVals.get(i).getVal();
if (mYVals.get(i).getVal() > mYMax)
mYMax = mYVals.get(i).getVal();
}
}
/**
* calculates the sum of all y-values
*/
private void calcYValueSum() {
mYValueSum = 0;
for (int i = 0; i < getYValSize(); i++) {
mYValueSum += Math.abs(getYVals().get(i).getVal());
}
}
/**
* extract all different types of series and store them in seperate arrays
*/
private void calcTypeSeries() {
typeSeries = new ArrayList<ArrayList<Series>>();
for (int i = 0; i < getTypeCount(); i++) {
ArrayList<Series> series = new ArrayList<Series>();
for (int j = 0; j < mYVals.size(); j++) {
Series s = mYVals.get(j);
if (s.getType() == mDiffTypes.get(i)) {
series.add(s);
}
}
typeSeries.add(series);
}
}
private boolean alreadyCounted(ArrayList<Integer> countedTypes, int type) {
for (int i = 0; i < countedTypes.size(); i++) {
if (countedTypes.get(i) == type)
return true;
}
return false;
}
public int getTypeCount() {
return mDiffTypes.size();
}
public float getYMin() {
return mYMin;
}
public float getYMax() {
return mYMax;
}
public float getYValueSum() {
return mYValueSum;
}
/**
* Checks if the ChartData object contains valid data
*
* @return
*/
public boolean isValid() {
if (mXVals == null || mXVals.size() <= 1 || mYVals == null || mYVals.size() <= 1)
return false;
else
return true;
}
public ArrayList<String> getXVals() {
return mXVals;
}
public ArrayList<Series> getYVals() {
return mYVals;
}
public ArrayList<ArrayList<Series>> getTypeSeries() {
return typeSeries;
}
public int getXValSize() {
return mXVals.size();
}
public int getYValSize() {
return mYVals.size();
}
}

View file

@ -1,391 +1,385 @@
package com.github.mikephil.charting;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import java.util.ArrayList;
public class LineChart extends BarLineChartBase {
/** the radius of the circle-shaped value indicators */
protected float mCircleSize = 4f;
/** the radius of the circle-shaped value indicators */
protected float mCircleSize = 4f;
/** the width of the drawn data lines */
protected float mLineWidth = 1f;
/** the width of the drawn data lines */
protected float mLineWidth = 1f;
/** the width of the highlighning line */
protected float mHighlightWidth = 3f;
/** the width of the highlighning line */
protected float mHighlightWidth = 3f;
/** if true, the data will also be drawn filled */
protected boolean mDrawFilled = false;
/** if true, the data will also be drawn filled */
protected boolean mDrawFilled = false;
/** if true, drawing circles is enabled */
protected boolean mDrawCircles = true;
/** if true, drawing circles is enabled */
protected boolean mDrawCircles = true;
/** paint for the lines of the chart */
protected Paint mLinePaint;
/** paint for the filled are (if enabled) below the chart line */
protected Paint mFilledPaint;
/** paint for the filled are (if enabled) below the chart line */
protected Paint mFilledPaint;
/** paint for the outer circle of the value indicators */
protected Paint mCirclePaintOuter;
/** paint for the outer circle of the value indicators */
protected Paint mCirclePaintOuter;
/** paint for the inner circle of the value indicators */
protected Paint mCirclePaintInner;
/** paint for the inner circle of the value indicators */
protected Paint mCirclePaintInner;
public LineChart(Context context) {
super(context);
}
public LineChart(Context context) {
super(context);
}
public LineChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LineChart(Context context, AttributeSet attrs) {
super(context, attrs);
}
public LineChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
public LineChart(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void init() {
super.init();
@Override
protected void init() {
super.init();
mCircleSize = Utils.convertDpToPixel(mCircleSize);
mCircleSize = Utils.convertDpToPixel(mCircleSize);
mFilledPaint = new Paint();
mFilledPaint.setStyle(Paint.Style.FILL);
mFilledPaint.setColor(mColorDarkBlue);
mFilledPaint.setAlpha(130); // alpha ~55%
mLinePaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mLinePaint.setStrokeWidth(mLineWidth);
mLinePaint.setStyle(Paint.Style.STROKE);
mLinePaint.setColor(mColorDarkBlue);
// mLinePaint.setColor(mDrawColor);
mCirclePaintOuter = new Paint(Paint.ANTI_ALIAS_FLAG);
// mCirclePaint.setStrokeWidth(5f);
mCirclePaintOuter.setStyle(Paint.Style.FILL);
mCirclePaintOuter.setColor(mColorDarkBlue);
mFilledPaint = new Paint();
mFilledPaint.setStyle(Paint.Style.FILL);
mFilledPaint.setColor(mColorDarkBlue);
mFilledPaint.setAlpha(130); // alpha ~55%
mCirclePaintInner = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaintInner.setStyle(Paint.Style.FILL);
mCirclePaintInner.setColor(Color.WHITE);
mCirclePaintOuter = new Paint(Paint.ANTI_ALIAS_FLAG);
// mCirclePaint.setStrokeWidth(5f);
mCirclePaintOuter.setStyle(Paint.Style.FILL);
mCirclePaintOuter.setColor(mColorDarkBlue);
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setStyle(Paint.Style.STROKE);
mHighlightPaint.setStrokeWidth(2f);
mHighlightPaint.setColor(Color.rgb(255, 187, 115));
}
mCirclePaintInner = new Paint(Paint.ANTI_ALIAS_FLAG);
mCirclePaintInner.setStyle(Paint.Style.FILL);
mCirclePaintInner.setColor(Color.WHITE);
@Override
protected void prepareDataPaints(ColorTemplate ct) {
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setStyle(Paint.Style.STROKE);
mHighlightPaint.setStrokeWidth(2f);
mHighlightPaint.setColor(Color.rgb(255, 187, 115));
}
if (ct == null)
return;
@Override
protected void prepareDataPaints(ColorTemplate ct) {
mDrawPaints = new Paint[ct.getColors().size()];
if (ct == null)
return;
for (int i = 0; i < ct.getColors().size(); i++) {
mDrawPaints[i] = new Paint(Paint.ANTI_ALIAS_FLAG);
mDrawPaints[i].setStrokeWidth(mLineWidth);
mDrawPaints[i].setStyle(Style.STROKE);
mDrawPaints[i].setColor(ct.getColors().get(i));
}
}
mDrawPaints = new Paint[ct.getColors().size()];
@Override
protected void drawHighlights() {
for (int i = 0; i < ct.getColors().size(); i++) {
mDrawPaints[i] = new Paint(Paint.ANTI_ALIAS_FLAG);
mDrawPaints[i].setStrokeWidth(mLineWidth);
mDrawPaints[i].setStyle(Style.STROKE);
mDrawPaints[i].setColor(ct.getColors().get(i));
}
}
// if there are values to highlight and highlighnting is enabled, do it
if (mHighlightEnabled && valuesToHighlight()) {
@Override
protected void drawHighlights() {
for (int i = 0; i < mIndicesToHightlight.length; i++) {
// if there are values to highlight and highlighnting is enabled, do it
if (mHighlightEnabled && valuesToHighlight()) {
// RectF highlight = new RectF(mIndicesToHightlight[i] -
// mHighlightWidth / 2,
// mYChartMax, mIndicesToHightlight[i] + mHighlightWidth / 2,
// mYChartMin);
// transformRect(highlight);
// mDrawCanvas.drawRect(highlight, mHighlightPaint);
for (int i = 0; i < mIndicesToHightlight.length; i++) {
int index = mIndicesToHightlight[i];
// RectF highlight = new RectF(mIndicesToHightlight[i] -
// mHighlightWidth / 2,
// mYChartMax, mIndicesToHightlight[i] + mHighlightWidth / 2,
// mYChartMin);
// transformRect(highlight);
// mDrawCanvas.drawRect(highlight, mHighlightPaint);
// check outofbounds
if (index < mData.getYValSize() && index >= 0) {
int index = mIndicesToHightlight[i];
float[] pts = new float[] { index, mYChartMax, index, mYChartMin, 0,
mData.getYVals().get(index).getVal(), mDeltaX, mData.getYVals().get(index).getVal() };
// check outofbounds
if (index < mYVals.size() && index >= 0) {
transformPointArray(pts);
// draw the highlight lines
mDrawCanvas.drawLines(pts, mHighlightPaint);
}
}
}
}
float[] pts = new float[] {
index, mYChartMax, index, mYChartMin,
0, mYVals.get(index).getVal(), mDeltaX, mYVals.get(index).getVal()
};
/**
* draws the given y values to the screen
*/
@Override
protected void drawData() {
transformPointArray(pts);
// draw the highlight lines
mDrawCanvas.drawLines(pts, mHighlightPaint);
}
}
}
}
ArrayList<ArrayList<Series>> typeSeries = mData.getTypeSeries();
/**
* draws the given y values to the screen
*/
@Override
protected void drawData() {
for (int i = 0; i < mData.getTypeCount(); i++) {
Path p = new Path();
p.moveTo(0, mYVals.get(0).getVal());
ArrayList<Series> series = typeSeries.get(i);
for (int x = 1; x < mYVals.size(); x++) {
float[] valuePoints = new float[series.size() * 2];
p.lineTo(x, mYVals.get(x).getVal());
}
for (int j = 0; j < valuePoints.length; j += 2) {
valuePoints[j] = series.get(j / 2).getXIndex();
valuePoints[j + 1] = series.get(j / 2).getVal();
}
transformPath(p);
transformPointArray(valuePoints);
mDrawCanvas.drawPath(p, mLinePaint);
for (int j = 0; j < valuePoints.length - 2; j += 2) {
// if data is drawn filled
if (mDrawFilled) {
if (valuePoints[j] > mContentRect.right)
break;
Path filled = new Path();
filled.moveTo(0, mYVals.get(0).getVal());
// make sure the lines don't do shitty things outside bounds
if (j != 0 && valuePoints[j - 1] < mContentRect.left)
continue;
// create a new path
for (int x = 1; x < mYVals.size(); x++) {
filled.lineTo(x, mYVals.get(x).getVal());
}
// close up
filled.lineTo(mXVals.size() - 1, mYChartMin);
filled.lineTo(0f, mYChartMin);
filled.close();
transformPath(filled);
mDrawCanvas.drawPath(filled, mFilledPaint);
}
}
@Override
protected void drawValues() {
// if values are drawn
if (mDrawYValues && mYVals.size() < mMaxVisibleCount * mScaleX) {
float[] valuePoints = new float[mYVals.size() * 2];
for (int i = 0; i < valuePoints.length; i += 2) {
valuePoints[i] = i / 2;
valuePoints[i + 1] = mYVals.get(i / 2).getVal();
}
transformPointArray(valuePoints);
for (int i = 0; i < valuePoints.length; i += 2) {
if (mDrawUnitInChart) {
mDrawCanvas.drawText(
mFormatValue.format(mYVals.get(i / 2).getVal()) + mUnit,
valuePoints[i], valuePoints[i + 1] - 12, mValuePaint);
} else {
mDrawCanvas.drawText(
mFormatValue.format(mYVals.get(i / 2).getVal()),
valuePoints[i], valuePoints[i + 1] - 12, mValuePaint);
}
}
}
}
/**
* draws the circle value indicators
*/
@Override
protected void drawAdditional() {
// if drawing circles is enabled
if (mDrawCircles) {
float[] positions = new float[mYVals.size() * 2];
for (int i = 0; i < positions.length; i += 2) {
positions[i] = i / 2;
positions[i + 1] = mYVals.get(i / 2).getVal();
}
transformPointArray(positions);
for (int i = 0; i < positions.length; i += 2) {
// make sure the circles don't do shitty things outside bounds
if (positions[i] < mContentRect.left || positions[i] > mContentRect.right)
continue;
mDrawCanvas.drawCircle(positions[i], positions[i + 1], mCircleSize,
mCirclePaintOuter);
mDrawCanvas.drawCircle(positions[i], positions[i + 1], mCircleSize / 2,
mCirclePaintInner);
}
}
}
/**
* set this to true to enable the drawing of circle indicators
*
* @param enabled
*/
public void setDrawCircles(boolean enabled) {
this.mDrawCircles = enabled;
}
/**
* returns true if drawing circles is enabled, false if not
*
* @return
*/
public boolean isDrawCirclesEnabled() {
return mDrawCircles;
}
/**
* sets the size (radius) of the circle shpaed value indicators, default
* size = 4f
*
* @param size
*/
public void setCircleSize(float size) {
mCircleSize = Utils.convertDpToPixel(size);
}
/**
* returns the circlesize
*
* @param size
*/
public float getCircleSize(float size) {
return Utils.convertPixelsToDp(mCircleSize);
}
/**
* set if the chartdata should be drawn as a line or filled default = line /
* default = false, disabling this will give up to 20% performance boost on
* large datasets
*
* @param filled
*/
public void setDrawFilled(boolean filled) {
mDrawFilled = filled;
}
/**
* returns true if filled drawing is enabled, false if not
*
* @return
*/
public boolean isDrawFilledEnabled() {
return mDrawFilled;
}
/**
* set the line width of the chart (min = 0.5f, max = 10f); default 1f NOTE:
* thinner line == better performance, thicker line == worse performance
*
* @param width
*/
public void setLineWidth(float width) {
if (width < 0.5f)
width = 0.5f;
if (width > 10.0f)
width = 10.0f;
mLineWidth = width;
mLinePaint.setStrokeWidth(mLineWidth);
}
/**
* returns the width of the drawn chart line
*
* @return
*/
public float getLineWidth() {
return mLineWidth;
}
/**
* sets the color for the line paint
*
* @param color
*/
public void setLineColor(int color) {
mLinePaint.setColor(color);
}
/**
* sets the color for the outer circle paint
*
* @param color
*/
public void setCircleColor(int color) {
mCirclePaintOuter.setColor(color);
}
/**
* sets the color for the fill-paint
*
* @param color
*/
public void setFillColor(int color) {
mFilledPaint.setColor(color);
}
/**
* set the width of the highlightning lines, default 3f
*
* @param width
*/
public void setHighlightLineWidth(float width) {
mHighlightWidth = width;
}
/**
* returns the width of the highlightning line, default 3f
*
* @return
*/
public float getHighlightLineWidth() {
return mHighlightWidth;
}
@Override
public void setPaint(Paint p, int which) {
super.setPaint(p, which);
switch (which) {
case PAINT_FILLED:
mFilledPaint = p;
break;
case PAINT_LINE:
mLinePaint = p;
break;
case PAINT_CIRCLES_INNER:
mCirclePaintInner = p;
break;
case PAINT_CIRCLES_OUTER:
mCirclePaintOuter = p;
break;
case PAINT_HIGHLIGHT_LINE:
mHighlightPaint = p;
break;
}
}
mDrawCanvas.drawLine(valuePoints[j], valuePoints[j + 1], valuePoints[j + 2], valuePoints[j + 3],
mDrawPaints[i % mDrawPaints.length]);
}
}
// if data is drawn filled
if (mDrawFilled) {
Path filled = new Path();
filled.moveTo(0, mData.getYVals().get(0).getVal());
// create a new path
for (int x = 1; x < mData.getYValSize(); x++) {
filled.lineTo(x, mData.getYVals().get(x).getVal());
}
// close up
filled.lineTo(mData.getXValSize() - 1, mYChartMin);
filled.lineTo(0f, mYChartMin);
filled.close();
transformPath(filled);
mDrawCanvas.drawPath(filled, mFilledPaint);
}
}
@Override
protected void drawValues() {
// if values are drawn
if (mDrawYValues && mData.getYValSize() < mMaxVisibleCount * mScaleX) {
float[] valuePoints = new float[mData.getYValSize() * 2];
for (int i = 0; i < valuePoints.length; i += 2) {
valuePoints[i] = i / 2;
valuePoints[i + 1] = mData.getYVals().get(i / 2).getVal();
}
transformPointArray(valuePoints);
for (int i = 0; i < valuePoints.length; i += 2) {
if (mDrawUnitInChart) {
mDrawCanvas.drawText(mFormatValue.format(mData.getYVals().get(i / 2).getVal()) + mUnit,
valuePoints[i], valuePoints[i + 1] - 12, mValuePaint);
} else {
mDrawCanvas.drawText(mFormatValue.format(mData.getYVals().get(i / 2).getVal()), valuePoints[i],
valuePoints[i + 1] - 12, mValuePaint);
}
}
}
}
/**
* draws the circle value indicators
*/
@Override
protected void drawAdditional() {
// if drawing circles is enabled
if (mDrawCircles) {
ArrayList<ArrayList<Series>> typeSeries = mData.getTypeSeries();
for (int i = 0; i < mData.getTypeCount(); i++) {
ArrayList<Series> series = typeSeries.get(i);
float[] positions = new float[mData.getYValSize() * 2];
for (int j = 0; j < positions.length; j += 2) {
positions[j] = series.get(j / 2).getXIndex();
positions[j + 1] = series.get(j / 2).getVal();
}
transformPointArray(positions);
for (int j = 0; j < positions.length; j += 2) {
// make sure the circles don't do shitty things outside bounds
if (positions[j] < mContentRect.left || positions[j] > mContentRect.right)
continue;
mDrawCanvas.drawCircle(positions[j], positions[j + 1], mCircleSize, mCirclePaintOuter);
mDrawCanvas.drawCircle(positions[j], positions[j + 1], mCircleSize / 2, mCirclePaintInner);
}
}
}
}
/**
* set this to true to enable the drawing of circle indicators
*
* @param enabled
*/
public void setDrawCircles(boolean enabled) {
this.mDrawCircles = enabled;
}
/**
* returns true if drawing circles is enabled, false if not
*
* @return
*/
public boolean isDrawCirclesEnabled() {
return mDrawCircles;
}
/**
* sets the size (radius) of the circle shpaed value indicators, default size = 4f
*
* @param size
*/
public void setCircleSize(float size) {
mCircleSize = Utils.convertDpToPixel(size);
}
/**
* returns the circlesize
*
* @param size
*/
public float getCircleSize(float size) {
return Utils.convertPixelsToDp(mCircleSize);
}
/**
* set if the chartdata should be drawn as a line or filled default = line / default = false, disabling this will
* give up to 20% performance boost on large datasets
*
* @param filled
*/
public void setDrawFilled(boolean filled) {
mDrawFilled = filled;
}
/**
* returns true if filled drawing is enabled, false if not
*
* @return
*/
public boolean isDrawFilledEnabled() {
return mDrawFilled;
}
/**
* set the line width of the chart (min = 0.5f, max = 10f); default 1f NOTE: thinner line == better performance,
* thicker line == worse performance
*
* @param width
*/
public void setLineWidth(float width) {
if (width < 0.5f)
width = 0.5f;
if (width > 10.0f)
width = 10.0f;
mLineWidth = width;
for (int i = 0; i < mDrawPaints.length; i++) {
mDrawPaints[i].setStrokeWidth(mLineWidth);
}
}
/**
* returns the width of the drawn chart line
*
* @return
*/
public float getLineWidth() {
return mLineWidth;
}
/**
* sets the color for the outer circle paint
*
* @param color
*/
public void setCircleColor(int color) {
mCirclePaintOuter.setColor(color);
}
/**
* sets the color for the fill-paint
*
* @param color
*/
public void setFillColor(int color) {
mFilledPaint.setColor(color);
}
/**
* set the width of the highlightning lines, default 3f
*
* @param width
*/
public void setHighlightLineWidth(float width) {
mHighlightWidth = width;
}
/**
* returns the width of the highlightning line, default 3f
*
* @return
*/
public float getHighlightLineWidth() {
return mHighlightWidth;
}
@Override
public void setPaint(Paint p, int which) {
super.setPaint(p, which);
switch (which) {
case PAINT_FILLED:
mFilledPaint = p;
break;
case PAINT_CIRCLES_INNER:
mCirclePaintInner = p;
break;
case PAINT_CIRCLES_OUTER:
mCirclePaintOuter = p;
break;
case PAINT_HIGHLIGHT_LINE:
mHighlightPaint = p;
break;
}
}
}

View file

@ -1,21 +0,0 @@
package com.github.mikephil.charting;
public class LineSeries extends Series {
private int mLineIndex = 0;
private int mXIndex = 0;
public LineSeries(float val, int lineIndex, int xIndex) {
super(val);
mLineIndex = lineIndex;
mXIndex = xIndex;
}
public int getLineIndex() {
return mLineIndex;
}
public int getXIndex() {
return mXIndex;
}
}

File diff suppressed because it is too large Load diff

View file

@ -1,9 +0,0 @@
package com.github.mikephil.charting;
public class PieSeries extends Series {
public PieSeries(float val) {
super(val);
}
}

View file

@ -0,0 +1,13 @@
package com.github.mikephil.charting;
public class Point {
public double x;
public double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}

View file

@ -1,14 +1,96 @@
package com.github.mikephil.charting;
public abstract class Series {
import java.util.ArrayList;
private float mVal = 0f;
public Series(float val) {
mVal = val;
}
public float getVal() {
return mVal;
}
public class Series {
private float mVal = 0f;
private int mType = 0;
private int mXIndex = 0;
/**
* A series represents one single entry in the chart
*
* @param val
* the y value
* @param type
* the type (e.g. different lines in the line chart are of different types). The type can be seen as an
* id and can be chosen freely.
* @param xIndex
* the corresponding index in the x value array
*/
public Series(float val, int type, int xIndex) {
mVal = val;
mType = type;
mXIndex = xIndex;
}
public void setType(int type) {
this.mType = type;
}
public int getType() {
return mType;
}
public int getXIndex() {
return mXIndex;
}
/**
* Convenience method to create a series of double values
*
* @param yValues
* @return
*/
public static ArrayList<Series> makeSeries(double[] yValues) {
ArrayList<Series> series = new ArrayList<Series>();
for (int i = 0; i < yValues.length; i++) {
series.add(new Series((float) yValues[i], 0, i));
}
return series;
}
/**
* Convenience method to create multiple series of different types of various double value arrays. Each double array
* represents one type starting at 0.
*
* @param yValues
* @return
*/
public static ArrayList<Series> makeMultipleSeries(ArrayList<Double[]> yValues) {
ArrayList<Series> series = new ArrayList<Series>();
int sizeOfFirst = yValues.get(0).length;
for (int i = 0; i < yValues.size(); i++) {
Double[] curValues = yValues.get(i);
if (curValues.length != sizeOfFirst) {
throw new IllegalArgumentException("Array sizes do not match");
}
for (int j = 0; j < curValues.length; j++) {
series.add(new Series(curValues[j].floatValue(), i, j));
}
}
return series;
}
/**
* Convenience method to add a series. The new series has to be the same size as the old. If you want to create a
* different sized series, please add manually.
*
* @param series
* @param yValues
* @param type
*/
public static void addSeries(ArrayList<Series> series, double[] yValues, int type) {
for (int i = 0; i < yValues.length; i++) {
series.add(new Series((float) yValues[i], type, i));
}
}
public float getVal() {
return mVal;
}
}