It is now possible to programatically set the number of digits to use for legend and values.

This commit is contained in:
Philipp Jahoda 2014-05-05 14:17:35 +02:00
parent 31433ac126
commit fd4008eaa5
4 changed files with 230 additions and 57 deletions

View file

@ -32,13 +32,14 @@ public class BarChartActivity extends Activity implements OnSeekBarChangeListene
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);

View file

@ -10,6 +10,7 @@ import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
@ -34,6 +35,12 @@ public abstract class BarLineChartBase extends Chart {
*/
protected int mLegendGridModulus = 1;
/**
* indicates how many digits should be used for the y-legend, -1 means
* automatically calculate
*/
protected int mYLegendDigitsToUse = -1;
/** the number of y-legend entries the chart has */
protected int mYLegendCount = 9;
@ -54,7 +61,7 @@ public abstract class BarLineChartBase extends Chart {
/** if true, dragging / scaling is enabled for the chart */
protected boolean mDragEnabled = true;
/**
* if true, the y-legend values will be rounded - the legend entry count
* will only be approximated
@ -78,7 +85,7 @@ public abstract class BarLineChartBase extends Chart {
/** paint for the y-legend values */
protected Paint mYLegendPaint;
/** paint used for highlighting values */
protected Paint mHighlightPaint;
@ -126,7 +133,7 @@ public abstract class BarLineChartBase extends Chart {
// mGridBackgroundPaint.setColor(Color.WHITE);
mGridBackgroundPaint.setColor(Color.rgb(240, 240, 240)); // light
// grey
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setStyle(Paint.Style.STROKE);
mHighlightPaint.setStrokeWidth(2f);
@ -167,7 +174,7 @@ public abstract class BarLineChartBase extends Chart {
drawXLegend();
drawYLegend();
drawMarkerView();
drawDescription();
@ -220,13 +227,7 @@ public abstract class BarLineChartBase extends Chart {
protected DecimalFormat mFormatValue = null;
/** the number of digits the y-legend is formatted with */
protected int mYLegendFormatDigits = 1;
/**
* the number of digits values that are drawn in the chart are formatted
* with
*/
protected int mValueFormatDigits = 1;
protected int mYLegendFormatDigits = -1;
/**
* calculates the required number of digits for the y-legend and for the
@ -239,10 +240,16 @@ public abstract class BarLineChartBase extends Chart {
bonus++;
// calcualte the step between the legend entries and get the needed
// digits
mYLegendFormatDigits = Utils.getLegendFormatDigits(mYLegend[2] - mYLegend[1], bonus);
// digits, -1 means calculate automatically, else the set value is used
if (mYLegendDigitsToUse == -1)
mYLegendFormatDigits = Utils.getLegendFormatDigits(mYLegend[2] - mYLegend[1], bonus);
else
mYLegendFormatDigits = mYLegendDigitsToUse;
mValueFormatDigits = Utils.getFormatDigits(mDeltaY);
if (mValueDigitsToUse == -1)
mValueFormatDigits = Utils.getFormatDigits(mDeltaY);
else
mValueFormatDigits = mValueDigitsToUse;
StringBuffer a = new StringBuffer();
for (int i = 0; i < mYLegendFormatDigits; i++) {
@ -393,6 +400,7 @@ public abstract class BarLineChartBase extends Chart {
*/
protected void drawXLegend() {
// pre allocate to save performance (dont allocate in loop)
float[] position = new float[] {
0f, 0f
};
@ -407,6 +415,15 @@ public abstract class BarLineChartBase extends Chart {
if (position[0] >= mOffsetLeft && position[0] <= getWidth() - mOffsetRight + 10) {
// Rect rect = new Rect();
// mXLegendPaint.getTextBounds(mXVals.get(i), 0,
// mXVals.get(i).length(), rect);
//
// float toRight = rect.width() / 2;
//
// // make sure
// if(i == 0) toRight = rect.width();
mDrawCanvas.drawText(mXVals.get(i), position[0], mOffsetTop - 5,
mXLegendPaint);
}
@ -419,20 +436,30 @@ public abstract class BarLineChartBase extends Chart {
*/
protected void drawYLegend() {
float[] yPoints = new float[mYLegend.length * 2];
float[] positions = new float[mYLegend.length * 2];
for (int i = 0; i < yPoints.length; i += 2) {
yPoints[i] = 0;
yPoints[i + 1] = mYLegend[i / 2];
for (int i = 0; i < positions.length; i += 2) {
positions[i] = 0;
positions[i + 1] = mYLegend[i / 2];
}
transformPointArrayNoTouch(yPoints);
// y-axis cannot be scaled, therefore transform without the touch matrix
transformPointArrayNoTouch(positions);
for (int i = 0; i < positions.length; i += 2) {
if (mYLegend[i / 2] != null) {
float yPos = positions[i + 1] + 8;
// lower the position of the top y-legend entry so that it does
// not interfear with the x-legend
if (i >= positions.length - 2)
yPos = positions[i + 1] + 14;
for (int i = 0; i < yPoints.length; i += 2) {
if (mYLegend[i / 2] != null)
mDrawCanvas.drawText(mFormatYLegend.format(mYLegend[i / 2]),
yPoints[i] - 10,
yPoints[i + 1] + 8, mYLegendPaint);
positions[i] - 10,
yPos, mYLegendPaint);
}
}
}
@ -696,17 +723,19 @@ public abstract class BarLineChartBase extends Chart {
width = 3.0f;
mGridWidth = width;
}
/**
* set this to true to enable dragging / scaling for the chart
*
* @param enabled
*/
public void setDragEnabled(boolean enabled) {
this.mDragEnabled = enabled;
}
/**
* returns true if dragging / scaling is enabled for the chart, false if not
*
* @return
*/
public boolean isDragEnabled() {
@ -721,14 +750,14 @@ public abstract class BarLineChartBase extends Chart {
* @return
*/
public int getIndexByTouchPoint(float x, float y) {
// create an array of the touch-point
float[] pts = new float[2];
pts[0] = x;
pts[1] = y;
Matrix tmp = new Matrix();
// invert all matrixes to convert back to the original value
mMatrixOffset.invert(tmp);
tmp.mapPoints(pts);
@ -743,14 +772,14 @@ public abstract class BarLineChartBase extends Chart {
double base = Math.floor(touchPointIndex);
int index = (int) base;
if(this instanceof LineChart) {
if (this instanceof LineChart) {
// check if we are more than half of a x-value or not
if (touchPointIndex - base > 0.5) {
index = (int) base + 1;
}
}
}
return index;
}
@ -766,6 +795,54 @@ public abstract class BarLineChartBase extends Chart {
return mYVals.get(getIndexByTouchPoint(x, y));
}
/**
* sets a typeface for the paint object of the x-legend
*
* @param t
*/
public void setXLegendTypeface(Typeface t) {
mXLegendPaint.setTypeface(t);
}
/**
* sets a typeface for the paint object of the y-legend
*
* @param t
*/
public void setYLegendTypeface(Typeface t) {
mYLegendPaint.setTypeface(t);
}
/**
* sets a typeface for both x and y-legend paints
*
* @param t
*/
public void setLegendTypeface(Typeface t) {
setXLegendTypeface(t);
setYLegendTypeface(t);
}
/**
* sets the number of y-legend digits to use, if set to -1, digits will be
* automatically calculated
*
* @param digits
*/
public void setLegendDigits(int digits) {
mYLegendDigitsToUse = digits;
}
/**
* returns the number of y-legend digits that is set to use, -1 means auto
* calculate
*
* @return
*/
public int getLegendDigits() {
return mYLegendDigitsToUse;
}
@Override
public void setPaint(Paint p, int which) {
super.setPaint(p, which);

View file

@ -8,6 +8,7 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.Paint;
import android.graphics.Typeface;
import android.graphics.Paint.Align;
import android.graphics.Path;
import android.graphics.PointF;
@ -37,6 +38,17 @@ public abstract class Chart extends View {
protected int mColorDarkBlue = Color.rgb(41, 128, 186);
protected int mColorDarkRed = Color.rgb(232, 76, 59);
/**
* defines the number of digits to use for all printed values, -1 means
* automatically determine
*/
protected int mValueDigitsToUse = -1;
/**
* defines the number of digits all printed values
*/
protected int mValueFormatDigits = -1;
/** the total sum of all y-values */
protected float mYValueSum = 0f;
@ -77,13 +89,38 @@ public abstract class Chart extends View {
/** the minimum y-value in the y-value array */
protected float mYMin = 0.0f;
/**
* colortemplate containing all the colors used by the chart
*/
protected ColorTemplate mColorTemplate;
/**
* paint object used for darwing the bitmap to the screen
*/
protected Paint mDrawPaint;
/**
* paint object used for drawing the description text in the bottom right
* corner of the chart
*/
protected Paint mDescPaint;
/**
* paint object for drawing the information text when there are no values in
* the chart
*/
protected Paint mInfoPaint;
/**
* paint object for drawing values (text representing values of chart
* entries)
*/
protected Paint mValuePaint;
/**
* paint objects used for drawing (e.g. the bars of a chart) usually, each
* paint object has a different color
*/
protected Paint[] mDrawPaints;
/** description text that appears in the bottom right corner of the chart */
@ -165,7 +202,7 @@ public abstract class Chart extends View {
mXVals = new ArrayList<String>();
mYVals = new ArrayList<Float>();
mDrawPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDrawPaint = new Paint();
mDescPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mDescPaint.setColor(Color.BLACK);
@ -431,6 +468,7 @@ public abstract class Chart extends View {
/**
* calculates the approximate width of a text, depending on a demo text
* avoid repeated calls (e.g. inside drawing methods)
*
* @param paint
* @param demoText
@ -484,11 +522,17 @@ public abstract class Chart extends View {
return mListener.onTouch(this, event);
}
/**
* disables intercept touchevents
*/
public void disableScroll() {
ViewParent parent = getParent();
parent.requestDisallowInterceptTouchEvent(true);
}
/**
* enables intercept touchevents
*/
public void enableScroll() {
ViewParent parent = getParent();
parent.requestDisallowInterceptTouchEvent(false);
@ -569,11 +613,14 @@ public abstract class Chart extends View {
/**
* returns true if there are values to highlight, false if there are not
* checks if the highlight array is null, has a length of zero or contains
* -1
*
* @return
*/
public boolean valuesToHighlight() {
return mIndicesToHightlight == null || mIndicesToHightlight.length == 0 ? false : true;
return mIndicesToHightlight == null || mIndicesToHightlight.length == 0
|| mIndicesToHightlight[0] == -1 ? false : true;
}
/**
@ -591,10 +638,7 @@ public abstract class Chart extends View {
if (mSelectionListener != null) {
if (indices == null)
return;
if (indices[0] == -1)
if (!valuesToHighlight())
mSelectionListener.onNothingSelected();
else {
@ -639,18 +683,22 @@ public abstract class Chart extends View {
int index = mIndicesToHightlight[0];
float value = mYVals.get(index);
// position of the marker depends on selected value index and value
float[] pts = new float[] {
index, value
};
transformPointArray(pts);
mMarkerPosX = pts[0] - mMarkerView.getWidth() / 2f;
mMarkerPosY = pts[1] - mMarkerView.getHeight();
Log.i("abc", "h: " + mMarkerView.getHeight() + ", w: " + mMarkerView.getWidth());
mMarkerPosX = pts[0] - mMarkerView.getWidth() / 2f;
mMarkerPosY = pts[1] - mMarkerView.getHeight();
Log.i("", "h: " + mMarkerView.getHeight() + ", w: " + mMarkerView.getWidth());
// translate to marker position
mDrawCanvas.translate(mMarkerPosX, mMarkerPosY);
mMarkerView.draw(mDrawCanvas);
// translate back
mDrawCanvas.translate(-mMarkerPosX, -mMarkerPosY);
}
@ -669,6 +717,15 @@ public abstract class Chart extends View {
this.mListener = l;
}
/**
* set a selection listener for the chart
*
* @param l
*/
public void setOnChartValueSelectedListener(OnChartValueSelectedListener l) {
this.mSelectionListener = l;
}
/**
* if set to true, value highlightning is enabled
*
@ -871,7 +928,8 @@ public abstract class Chart extends View {
public void setMarkerView(View v) {
mMarkerView = new RelativeLayout(getContext());
mMarkerView.setLayoutParams(new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT,
mMarkerView.setLayoutParams(new RelativeLayout.LayoutParams(
RelativeLayout.LayoutParams.WRAP_CONTENT,
RelativeLayout.LayoutParams.WRAP_CONTENT));
mMarkerView.addView(v);
@ -1043,12 +1101,41 @@ public abstract class Chart extends View {
}
/**
* set a selection listener for the chart
* sets a typeface for the value-paint
*
* @param l
* @param t
*/
public void setOnChartValueSelectedListener(OnChartValueSelectedListener l) {
this.mSelectionListener = l;
public void setValueTypeface(Typeface t) {
mValuePaint.setTypeface(t);
}
/**
* sets the typeface for the description paint
*
* @param t
*/
public void setDescriptionTypeface(Typeface t) {
mDescPaint.setTypeface(t);
}
/**
* sets the number of digits that should be used for all printed values (if
* this is set to -1, digits will be calculated automatically), default -1
*
* @param digits
*/
public void setValueDigits(int digits) {
mValueDigitsToUse = digits;
}
/**
* returns the number of digits used to format the prited values of the
* chart (-1 means digits are calculated automatically)
*
* @return
*/
public int getValueDigits() {
return mValueDigitsToUse;
}
/**

View file

@ -9,6 +9,7 @@ import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.graphics.RectF;
import android.graphics.Typeface;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@ -168,19 +169,17 @@ public class PieChart extends Chart {
/** the decimalformat responsible for formatting the values in the chart */
protected DecimalFormat mFormatValue = null;
/**
* the number of digits values that are drawn in the chart are formatted
* with
*/
protected int mValueFormatDigits = 1;
/**
* calculates the required number of digits for the y-legend and for the
* values that might be drawn in the chart (if enabled)
*/
protected void calcFormats() {
mValueFormatDigits = Utils.getPieFormatDigits(mDeltaY);
// -1 means calculate digits
if (mValueDigitsToUse == -1)
mValueFormatDigits = Utils.getPieFormatDigits(mDeltaY);
else
mValueFormatDigits = mValueDigitsToUse;
StringBuffer b = new StringBuffer();
for (int i = 0; i < mValueFormatDigits; i++) {
@ -720,6 +719,15 @@ public class PieChart extends Chart {
return dist;
}
/**
* sets the typeface for the center-text paint
*
* @param t
*/
public void setCenterTextTypeface(Typeface t) {
mCenterTextPaint.setTypeface(t);
}
@Override
public void setPaint(Paint p, int which) {
super.setPaint(p, which);