From 5f1448715e8aa125f7eaeed7c2d92c28606f284e Mon Sep 17 00:00:00 2001 From: Daniel Malmqvist Date: Mon, 1 Feb 2016 12:46:45 +0100 Subject: [PATCH 1/8] Added attributes --- .../com/github/mikephil/charting/charts/BarChart.java | 4 ++-- .../mikephil/charting/charts/BarLineChartBase.java | 4 ++-- .../com/github/mikephil/charting/charts/BubbleChart.java | 4 ++-- .../mikephil/charting/charts/CandleStickChart.java | 4 ++-- .../src/com/github/mikephil/charting/charts/Chart.java | 9 +++++---- .../github/mikephil/charting/charts/CombinedChart.java | 4 ++-- .../mikephil/charting/charts/HorizontalBarChart.java | 4 ++-- .../com/github/mikephil/charting/charts/LineChart.java | 4 ++-- .../com/github/mikephil/charting/charts/PieChart.java | 4 ++-- .../mikephil/charting/charts/PieRadarChartBase.java | 4 ++-- .../com/github/mikephil/charting/charts/RadarChart.java | 4 ++-- .../github/mikephil/charting/charts/ScatterChart.java | 4 ++-- 12 files changed, 27 insertions(+), 26 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java index c2dc39b3c3..3ea4340a77 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarChart.java @@ -53,8 +53,8 @@ public BarChart(Context context, AttributeSet attrs, int defStyle) { } @Override - protected void init() { - super.init(); + protected void init(AttributeSet attrs) { + super.init(attrs); mRenderer = new BarChartRenderer(this, mAnimator, mViewPortHandler); mXAxisRenderer = new XAxisRendererBarChart(mViewPortHandler, mXAxis, mLeftAxisTransformer, this); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java index 7647f13cff..bf8736d95e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BarLineChartBase.java @@ -152,8 +152,8 @@ public BarLineChartBase(Context context) { } @Override - protected void init() { - super.init(); + protected void init(AttributeSet attrs) { + super.init(attrs); mAxisLeft = new YAxis(AxisDependency.LEFT); mAxisRight = new YAxis(AxisDependency.RIGHT); diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java index fe7942f0a2..6cc05d2bbe 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/BubbleChart.java @@ -32,8 +32,8 @@ public BubbleChart(Context context, AttributeSet attrs, int defStyle) { } @Override - protected void init() { - super.init(); + protected void init(AttributeSet attrs) { + super.init(attrs); mRenderer = new BubbleChartRenderer(this, mAnimator, mViewPortHandler); } diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java index 12f8dad9fd..aa30e4703b 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/CandleStickChart.java @@ -28,8 +28,8 @@ public CandleStickChart(Context context, AttributeSet attrs, int defStyle) { } @Override - protected void init() { - super.init(); + protected void init(AttributeSet attrs) { + super.init(attrs); mRenderer = new CandleStickChartRenderer(this, mAnimator, mViewPortHandler); mXChartMin = -0.5f; diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java index cde8f605ee..5fb91c627e 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/Chart.java @@ -189,7 +189,7 @@ public abstract class Chart Date: Mon, 1 Feb 2016 12:58:25 +0100 Subject: [PATCH 2/8] Added gradient background color to linechart --- MPChartLib/res/values/attr.xml | 7 ++ .../mikephil/charting/charts/LineChart.java | 18 +++- .../charting/renderer/LineChartRenderer.java | 102 +++++++++--------- 3 files changed, 74 insertions(+), 53 deletions(-) create mode 100644 MPChartLib/res/values/attr.xml diff --git a/MPChartLib/res/values/attr.xml b/MPChartLib/res/values/attr.xml new file mode 100644 index 0000000000..0302492260 --- /dev/null +++ b/MPChartLib/res/values/attr.xml @@ -0,0 +1,7 @@ + + + + + + + \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java index 87652b2f61..c5e2802c52 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/LineChart.java @@ -2,8 +2,11 @@ package com.github.mikephil.charting.charts; import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.Color; import android.util.AttributeSet; +import com.github.mikephil.charting.R; import com.github.mikephil.charting.data.LineData; import com.github.mikephil.charting.interfaces.dataprovider.LineDataProvider; import com.github.mikephil.charting.renderer.LineChartRenderer; @@ -31,7 +34,20 @@ public LineChart(Context context, AttributeSet attrs, int defStyle) { protected void init(AttributeSet attrs) { super.init(attrs); - mRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); + LineChartRenderer lineChartRenderer = new LineChartRenderer(this, mAnimator, mViewPortHandler); + if (attrs != null) { + TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.LineChart); + boolean hasGradientBackground = typedArray.hasValue(R.styleable.LineChart_gradient_top_background) || typedArray.hasValue(R.styleable.LineChart_gradient_bottom_background); + int topBackgroundColor = typedArray.getColor(R.styleable.LineChart_gradient_top_background, Color.TRANSPARENT); + int bottomBackgroundColor = typedArray.getColor(R.styleable.LineChart_gradient_bottom_background, Color.TRANSPARENT); + typedArray.recycle(); + + if (hasGradientBackground) { + lineChartRenderer.setBackgroundGradientColors(topBackgroundColor, bottomBackgroundColor); + } + } + + mRenderer = lineChartRenderer; } @Override diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index 7708cfdd93..dc51614e98 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -3,9 +3,10 @@ import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Color; +import android.graphics.LinearGradient; import android.graphics.Paint; import android.graphics.Path; -import android.graphics.drawable.Drawable; +import android.graphics.Shader; import com.github.mikephil.charting.animation.ChartAnimator; import com.github.mikephil.charting.buffer.CircleBuffer; @@ -20,10 +21,9 @@ import com.github.mikephil.charting.utils.Transformer; import com.github.mikephil.charting.utils.ViewPortHandler; -import java.lang.ref.WeakReference; import java.util.List; -public class LineChartRenderer extends LineRadarRenderer { +public class LineChartRenderer extends LineScatterCandleRadarRenderer { protected LineDataProvider mChart; @@ -36,7 +36,7 @@ public class LineChartRenderer extends LineRadarRenderer { * Bitmap object used for drawing the paths (otherwise they are too long if * rendered directly on the canvas) */ - protected WeakReference mDrawBitmap; + protected Bitmap mDrawBitmap; /** * on this canvas, the paths are rendered, it is initialized with the @@ -44,17 +44,16 @@ public class LineChartRenderer extends LineRadarRenderer { */ protected Canvas mBitmapCanvas; - /** - * the bitmap configuration to be used - */ - protected Bitmap.Config mBitmapConfig = Bitmap.Config.ARGB_8888; - protected Path cubicPath = new Path(); protected Path cubicFillPath = new Path(); protected LineBuffer[] mLineBuffers; protected CircleBuffer[] mCircleBuffers; + private int mTopBackgroundColor; + private int mBottomBackgroundColor; + private boolean mHasGradientBackground; + private Paint mGradientBackgroundPaint; public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -87,18 +86,18 @@ public void drawData(Canvas c) { int height = (int) mViewPortHandler.getChartHeight(); if (mDrawBitmap == null - || (mDrawBitmap.get().getWidth() != width) - || (mDrawBitmap.get().getHeight() != height)) { + || (mDrawBitmap.getWidth() != width) + || (mDrawBitmap.getHeight() != height)) { if (width > 0 && height > 0) { - mDrawBitmap = new WeakReference(Bitmap.createBitmap(width, height, mBitmapConfig)); - mBitmapCanvas = new Canvas(mDrawBitmap.get()); + mDrawBitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_4444); + mBitmapCanvas = new Canvas(mDrawBitmap); } else return; } - mDrawBitmap.get().eraseColor(Color.TRANSPARENT); + mDrawBitmap.eraseColor(Color.TRANSPARENT); LineData lineData = mChart.getLineData(); @@ -108,7 +107,7 @@ public void drawData(Canvas c) { drawDataSet(c, set); } - c.drawBitmap(mDrawBitmap.get(), 0, 0, mRenderPaint); + c.drawBitmap(mDrawBitmap, 0, 0, mRenderPaint); } protected void drawDataSet(Canvas c, ILineDataSet dataSet) { @@ -259,14 +258,7 @@ protected void drawCubicFill(Canvas c, ILineDataSet dataSet, Path spline, Transf trans.pathValueToPixel(spline); - final Drawable drawable = dataSet.getFillDrawable(); - if (drawable != null) { - - drawFilledPath(c, spline, drawable); - } else { - - drawFilledPath(c, spline, dataSet.getFillColor(), dataSet.getFillAlpha()); - } + drawFilledPath(c, spline, dataSet.getFillColor(), dataSet.getFillAlpha()); } /** @@ -363,14 +355,33 @@ protected void drawLinearFill(Canvas c, ILineDataSet dataSet, int minx, trans.pathValueToPixel(filled); - final Drawable drawable = dataSet.getFillDrawable(); - if (drawable != null) { - - drawFilledPath(c, filled, drawable); - } else { + drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); + } - drawFilledPath(c, filled, dataSet.getFillColor(), dataSet.getFillAlpha()); + /** + * Draws the provided path in filled mode with the provided color and alpha. + * Special thanks to Angelo Suzuki (https://github.com/tinsukE) for this. + * + * @param c + * @param filledPath + * @param fillColor + * @param fillAlpha + */ + protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fillAlpha) { + c.save(); + c.clipPath(filledPath); + + if (mHasGradientBackground) { + LinearGradient shader = new LinearGradient(0, 0, 0, c.getHeight(), mTopBackgroundColor, mBottomBackgroundColor, Shader.TileMode.MIRROR); + mGradientBackgroundPaint.setShader(shader); + c.drawRect(0, 0, c.getWidth(), c.getHeight(), mGradientBackgroundPaint); } + else { + int color = (fillAlpha << 24) | (fillColor & 0xffffff); + c.drawColor(color); + } + + c.restore(); } /** @@ -576,35 +587,22 @@ public void drawHighlighted(Canvas c, Highlight[] indices) { } } - /** - * Sets the Bitmap.Config to be used by this renderer. - * Default: Bitmap.Config.ARGB_8888 - * Use Bitmap.Config.ARGB_4444 to consume less memory. - * - * @param config - */ - public void setBitmapConfig(Bitmap.Config config) { - mBitmapConfig = config; - releaseBitmap(); - } - - /** - * Returns the Bitmap.Config that is used by this renderer. - * - * @return - */ - public Bitmap.Config getBitmapConfig() { - return mBitmapConfig; - } - /** * Releases the drawing bitmap. This should be called when {@link LineChart#onDetachedFromWindow()}. */ public void releaseBitmap() { if (mDrawBitmap != null) { - mDrawBitmap.get().recycle(); - mDrawBitmap.clear(); + mDrawBitmap.recycle(); mDrawBitmap = null; } } + + public void setBackgroundGradientColors(int topBackgroundColor, int bottomBackgroundColor) { + mGradientBackgroundPaint = new Paint(); + + mHasGradientBackground = true; + + mTopBackgroundColor = topBackgroundColor; + mBottomBackgroundColor = bottomBackgroundColor; + } } From 2e5030128b177c5c11fb5e0e72b65491b89b751d Mon Sep 17 00:00:00 2001 From: Daniel Malmqvist Date: Wed, 3 Feb 2016 09:26:37 +0100 Subject: [PATCH 3/8] Speed fix --- .../mikephil/charting/renderer/LineChartRenderer.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java index dc51614e98..1c48f6a795 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/LineChartRenderer.java @@ -54,6 +54,8 @@ public class LineChartRenderer extends LineScatterCandleRadarRenderer { private int mBottomBackgroundColor; private boolean mHasGradientBackground; private Paint mGradientBackgroundPaint; + private LinearGradient mGradientShader; + private int mGradientShaderHeight; public LineChartRenderer(LineDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) { @@ -372,8 +374,11 @@ protected void drawFilledPath(Canvas c, Path filledPath, int fillColor, int fill c.clipPath(filledPath); if (mHasGradientBackground) { - LinearGradient shader = new LinearGradient(0, 0, 0, c.getHeight(), mTopBackgroundColor, mBottomBackgroundColor, Shader.TileMode.MIRROR); - mGradientBackgroundPaint.setShader(shader); + if (mGradientShader == null || mGradientShaderHeight != c.getHeight()) { + mGradientShaderHeight = c.getHeight(); + mGradientShader = new LinearGradient(0, 0, 0, mGradientShaderHeight, mTopBackgroundColor, mBottomBackgroundColor, Shader.TileMode.MIRROR); + mGradientBackgroundPaint.setShader(mGradientShader); + } c.drawRect(0, 0, c.getWidth(), c.getHeight(), mGradientBackgroundPaint); } else { From 7e4ba2c861dfce51aba02c5541737f7867e022cb Mon Sep 17 00:00:00 2001 From: Daniel Malmqvist Date: Wed, 3 Feb 2016 11:35:53 +0100 Subject: [PATCH 4/8] Added iconPieChart --- MPChartLib/res/values/attr.xml | 7 - MPChartLib/res/values/attrs.xml | 14 ++ .../charting/charts/IconPieChart.java | 45 +++++ .../charting/data/IconPieDataSet.java | 47 +++++ .../renderer/IconPieChartRenderer.java | 186 ++++++++++++++++++ 5 files changed, 292 insertions(+), 7 deletions(-) delete mode 100644 MPChartLib/res/values/attr.xml create mode 100644 MPChartLib/res/values/attrs.xml create mode 100644 MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/data/IconPieDataSet.java create mode 100644 MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java diff --git a/MPChartLib/res/values/attr.xml b/MPChartLib/res/values/attr.xml deleted file mode 100644 index 0302492260..0000000000 --- a/MPChartLib/res/values/attr.xml +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/MPChartLib/res/values/attrs.xml b/MPChartLib/res/values/attrs.xml new file mode 100644 index 0000000000..55de0407b4 --- /dev/null +++ b/MPChartLib/res/values/attrs.xml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java new file mode 100644 index 0000000000..ec0815d351 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java @@ -0,0 +1,45 @@ +package com.github.mikephil.charting.charts; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.PointF; +import android.util.AttributeSet; + +import com.github.mikephil.charting.R; +import com.github.mikephil.charting.renderer.IconPieChartRenderer; + +public class IconPieChart extends PieChart { + public IconPieChart(Context context) { + super(context); + } + + public IconPieChart(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public IconPieChart(Context context, AttributeSet attrs, int defStyle) { + super(context, attrs, defStyle); + } + + @Override + protected void init(AttributeSet attrs) { + super.init(attrs); + + int iconWidth = (int) (24 * getResources().getDisplayMetrics().density); + int iconHeight = (int) (24 * getResources().getDisplayMetrics().density); + float chartInset = 1.3f; + float radiusIconDivider = 4f; + + if (attrs != null) { + TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.IconPieChart); + iconWidth = typedArray.getDimensionPixelSize(R.styleable.IconPieChart_icon_width, iconWidth); + iconHeight = typedArray.getDimensionPixelSize(R.styleable.IconPieChart_icon_height, iconHeight); + chartInset = typedArray.getFloat(R.styleable.IconPieChart_chart_inset, chartInset); + radiusIconDivider = typedArray.getFloat(R.styleable.IconPieChart_radius_icon_divider, radiusIconDivider); + + typedArray.recycle(); + } + + mRenderer = new IconPieChartRenderer(this, mAnimator, mViewPortHandler, getResources(), new PointF(iconWidth, iconHeight), chartInset, radiusIconDivider); + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/data/IconPieDataSet.java b/MPChartLib/src/com/github/mikephil/charting/data/IconPieDataSet.java new file mode 100644 index 0000000000..2b47f06d23 --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/data/IconPieDataSet.java @@ -0,0 +1,47 @@ +package com.github.mikephil.charting.data; + +import android.graphics.Color; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.List; + +public class IconPieDataSet extends PieDataSet { + private List> mIcons = new ArrayList<>(); + private int mInactiveColor = Color.GRAY; + + public IconPieDataSet(List yVals, String label, List> icons) { + super(yVals, label); + + mIcons = icons; + } + + @Override + public DataSet copy() { + List yVals = new ArrayList(); + + for (int i = 0; i < mYVals.size(); i++) { + yVals.add(mYVals.get(i).copy()); + } + + IconPieDataSet copied = new IconPieDataSet(yVals, getLabel(), mIcons); + copied.mColors = mColors; + copied.setSliceSpace(getSliceSpace()); + copied.setSelectionShift(getSelectionShift()); + copied.mIcons = new ArrayList<>(mIcons); + + return copied; + } + + public void setInactiveColor(int inactiveColor) { + mInactiveColor = inactiveColor; + } + + public int getInactiveColor() { + return mInactiveColor; + } + + public List> getIcons() { + return mIcons; + } +} diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java new file mode 100644 index 0000000000..36cbf52f1a --- /dev/null +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java @@ -0,0 +1,186 @@ +package com.github.mikephil.charting.renderer; + +import android.content.res.Resources; +import android.graphics.Bitmap; +import android.graphics.BitmapFactory; +import android.graphics.Canvas; +import android.graphics.PointF; +import android.graphics.RectF; +import android.util.Pair; + +import com.github.mikephil.charting.animation.ChartAnimator; +import com.github.mikephil.charting.charts.IconPieChart; +import com.github.mikephil.charting.data.Entry; +import com.github.mikephil.charting.data.IconPieDataSet; +import com.github.mikephil.charting.data.PieData; +import com.github.mikephil.charting.highlight.Highlight; +import com.github.mikephil.charting.interfaces.datasets.IPieDataSet; +import com.github.mikephil.charting.utils.ViewPortHandler; + +import java.lang.ref.WeakReference; +import java.util.HashMap; +import java.util.List; + +public class IconPieChartRenderer extends PieChartRenderer { + private final float mChartInset; + private final float mRadiusIconDivider; + protected IconPieChart mChart; + + private final Resources mResources; + private final PointF mIconSize; + private HashMap> mIcons = new HashMap<>(); + private int mIconXOffset; + private int mIconYOffset; + + public IconPieChartRenderer(IconPieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Resources resources, PointF iconSize, float chartInset, float radiusIconDivider) { + super(chart, animator, viewPortHandler); + + mChart = chart; + mResources = resources; + mIconSize = iconSize; + mChartInset = chartInset; + mRadiusIconDivider = radiusIconDivider; + } + + @Override + protected void drawDataSet(Canvas c, IPieDataSet dataSet) { + drawDataSet(c, (IconPieDataSet) dataSet); + } + + protected void drawDataSet(Canvas c, IconPieDataSet dataSet) { + float angle = 0; + float rotationAngle = mChart.getRotationAngle(); + + float[] drawAngles = mChart.getDrawAngles(); + + for (int j = 0; j < dataSet.getEntryCount(); j++) { + + float sliceAngle = drawAngles[j]; + float sliceSpace = dataSet.getSliceSpace(); + + Entry e = dataSet.getEntryForIndex(j); + + // draw only if the value is greater than zero + if ((Math.abs(e.getVal()) > 0.000001)) { + + if (mChart.valuesToHighlight() && !mChart.needsHighlight(e.getXIndex(), mChart.getData().getIndexOfDataSet(dataSet))) { + mRenderPaint.setColor(dataSet.getInactiveColor()); + } + else { + mRenderPaint.setColor(dataSet.getColor(j)); + } + + RectF rectInner = new RectF(mChart.getCircleBox()); + rectInner.inset(Math.max(mIconSize.x, mIconSize.y)*mChartInset, Math.max(mIconSize.x, mIconSize.y)*mChartInset); + + mBitmapCanvas.drawArc(rectInner, + rotationAngle + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), + (sliceAngle - sliceSpace / 2f) * mAnimator.getPhaseY(), + true, mRenderPaint); + } + + angle += sliceAngle * mAnimator.getPhaseX(); + } + } + + @Override + public void drawValues(Canvas c) { + + PointF center = mChart.getCenterCircleBox(); + + // get whole the radius + float r = mChart.getRadius(); + float rotationAngle = mChart.getRotationAngle(); + float[] drawAngles = mChart.getDrawAngles(); + float[] absoluteAngles = mChart.getAbsoluteAngles(); + + r -= Math.max(mIconSize.x, mIconSize.y) / mRadiusIconDivider; + + PieData data = mChart.getData(); + List dataSets = data.getDataSets(); + + boolean drawXVals = mChart.isDrawSliceTextEnabled(); + + int cnt = 0; + + for (int i = 0; i < dataSets.size(); i++) { + IconPieDataSet dataSet = (IconPieDataSet) dataSets.get(i); + + if (!dataSet.isDrawValuesEnabled() && !drawXVals) + continue; + + // apply the text-styling defined by the DataSet + applyValueTextStyle(dataSet); + + int entryCount = dataSet.getEntryCount(); + List> icons = dataSet.getIcons(); + + for (int j = 0, maxEntry = Math.min( + (int) Math.ceil(entryCount * mAnimator.getPhaseX()), entryCount); j < maxEntry; j++) { + + Pair iconPair = icons.get(j); + Entry entry = dataSet.getEntryForIndex(j); + + // offset needed to center the drawn text in the slice + float offset = drawAngles[cnt] / 2; + + float angle = (absoluteAngles[cnt] - offset) * mAnimator.getPhaseY(); + // calculate the text position + float x = (float) (r + * Math.cos(Math.toRadians(rotationAngle + angle)) + + center.x); + float y = (float) (r + * Math.sin(Math.toRadians(rotationAngle + angle)) + + center.y); + + + Integer icon; + if (mChart.valuesToHighlight() && !mChart.needsHighlight(entry.getXIndex(), mChart.getData().getIndexOfDataSet(dataSet))) { + icon = iconPair.second; + } + else { + icon = iconPair.first; + } + + if (icon != 0) { + Bitmap bitmap; + WeakReference wr = mIcons.get(icon); + if (wr != null) { + bitmap = wr.get(); + + if (bitmap == null) { + bitmap = BitmapFactory.decodeResource(mResources, icon); + mIcons.put(icon, new WeakReference<>(bitmap)); + + if (mIconSize.x > bitmap.getWidth()) { + mIconXOffset = (int) ((mIconSize.x - bitmap.getWidth()) / 2); + } + if (mIconSize.y > bitmap.getHeight()) { + mIconYOffset = (int) ((mIconSize.x - bitmap.getHeight()) / 2); + } + } + } + else { + bitmap = BitmapFactory.decodeResource(mResources, icon); + mIcons.put(icon, new WeakReference<>(bitmap)); + + if (mIconSize.x > bitmap.getWidth()) { + mIconXOffset = (int) ((mIconSize.x - bitmap.getWidth()) / 2); + } + if (mIconSize.y > bitmap.getHeight()) { + mIconYOffset = (int) ((mIconSize.x - bitmap.getHeight()) / 2); + } + } + + c.drawBitmap(bitmap, x - mIconSize.x / 2 + mIconXOffset, y - mIconSize.y / 2 + mIconYOffset, mValuePaint); + } + cnt++; + } + } + } + + @Override + public void drawHighlighted(Canvas c, Highlight[] indices) { + + } +} From 7d83e1fb411637a0680382996c0bca6324b9f524 Mon Sep 17 00:00:00 2001 From: Daniel Malmqvist Date: Wed, 3 Feb 2016 14:33:09 +0100 Subject: [PATCH 5/8] Added new fitscreen method for overriding minscaley --- .../charting/utils/ViewPortHandler.java | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java index a0384a8c51..ea6c9e42e7 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/ViewPortHandler.java @@ -230,14 +230,9 @@ public Matrix zoom(float scaleX, float scaleY, float x, float y) { return save; } - /** - * Resets all zooming and dragging and makes the chart fit exactly it's - * bounds. - */ - public Matrix fitScreen() { - + public Matrix fitScreen(float minScaleY) { mMinScaleX = 1f; - mMinScaleY = 1f; + mMinScaleY = minScaleY; Matrix save = new Matrix(); save.set(mMatrixTouch); @@ -250,13 +245,21 @@ public Matrix fitScreen() { vals[Matrix.MTRANS_X] = 0f; vals[Matrix.MTRANS_Y] = 0f; vals[Matrix.MSCALE_X] = 1f; - vals[Matrix.MSCALE_Y] = 1f; + vals[Matrix.MSCALE_Y] = mMinScaleY; save.setValues(vals); return save; } + /** + * Resets all zooming and dragging and makes the chart fit exactly it's + * bounds. + */ + public Matrix fitScreen() { + return fitScreen(1f); + } + /** * Centers the viewport around the specified position (x-index and y-value) * in the chart. Centering the viewport outside the bounds of the chart is From 3c60deb38fcd1e24d3c276ce1dd1d9e2691783de Mon Sep 17 00:00:00 2001 From: Daniel Malmqvist Date: Wed, 3 Feb 2016 15:45:19 +0100 Subject: [PATCH 6/8] Possibility to remove select effect when tapping inside the chart --- .../src/com/github/mikephil/charting/charts/PieChart.java | 8 ++++++++ .../charting/listener/PieRadarChartTouchListener.java | 6 ++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java index 07e769ff95..4752fe03e4 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java @@ -87,6 +87,7 @@ public class PieChart extends PieRadarChartBase { private float mCenterTextRadiusPercent = 1.f; protected float mMaxAngle = 360f; + private boolean mHoleSelectable; public PieChart(Context context) { super(context); @@ -647,4 +648,11 @@ protected void onDetachedFromWindow() { super.onDetachedFromWindow(); } + public boolean isHoleSelectable() { + return mHoleSelectable; + } + + public void setHoleSelectable(boolean holeSelectable) { + mHoleSelectable = holeSelectable; + } } diff --git a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java index 9163c823d8..af7ab73e84 100644 --- a/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java +++ b/MPChartLib/src/com/github/mikephil/charting/listener/PieRadarChartTouchListener.java @@ -154,8 +154,10 @@ public boolean onSingleTapUp(MotionEvent e) { float distance = mChart.distanceToCenter(e.getX(), e.getY()); // check if a slice was touched - if (distance > mChart.getRadius()) { - + if (distance > mChart.getRadius() || + (mChart instanceof PieChart + && !((PieChart) mChart).isHoleSelectable() + && (distance < (((PieChart)mChart).getHoleRadius()/100) * mChart.getRadius()))) { // if no slice was touched, highlight nothing if (mLastHighlighted == null) From e9be8f678173c0af3e8a27fae60a135cbe7e2ca1 Mon Sep 17 00:00:00 2001 From: Daniel Malmqvist Date: Mon, 15 Feb 2016 11:21:54 +0100 Subject: [PATCH 7/8] Updated iconpiechart to accept radius & thickness --- MPChartLib/res/values/attrs.xml | 3 +- .../charting/charts/IconPieChart.java | 9 +++-- .../renderer/IconPieChartRenderer.java | 33 ++++++++++++++++--- .../charting/renderer/PieChartRenderer.java | 3 +- 4 files changed, 37 insertions(+), 11 deletions(-) diff --git a/MPChartLib/res/values/attrs.xml b/MPChartLib/res/values/attrs.xml index 55de0407b4..7890e98030 100644 --- a/MPChartLib/res/values/attrs.xml +++ b/MPChartLib/res/values/attrs.xml @@ -3,7 +3,8 @@ - + + diff --git a/MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java b/MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java index ec0815d351..e7d45c3d63 100644 --- a/MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java +++ b/MPChartLib/src/com/github/mikephil/charting/charts/IconPieChart.java @@ -27,19 +27,22 @@ protected void init(AttributeSet attrs) { int iconWidth = (int) (24 * getResources().getDisplayMetrics().density); int iconHeight = (int) (24 * getResources().getDisplayMetrics().density); - float chartInset = 1.3f; float radiusIconDivider = 4f; + float circleRadius = 100; + float circleWidth = 10; if (attrs != null) { TypedArray typedArray = getContext().obtainStyledAttributes(attrs, R.styleable.IconPieChart); iconWidth = typedArray.getDimensionPixelSize(R.styleable.IconPieChart_icon_width, iconWidth); iconHeight = typedArray.getDimensionPixelSize(R.styleable.IconPieChart_icon_height, iconHeight); - chartInset = typedArray.getFloat(R.styleable.IconPieChart_chart_inset, chartInset); radiusIconDivider = typedArray.getFloat(R.styleable.IconPieChart_radius_icon_divider, radiusIconDivider); + circleRadius = typedArray.getDimension(R.styleable.IconPieChart_circle_radius, 100); + circleWidth = typedArray.getDimension(R.styleable.IconPieChart_circle_thickness, 10); + typedArray.recycle(); } - mRenderer = new IconPieChartRenderer(this, mAnimator, mViewPortHandler, getResources(), new PointF(iconWidth, iconHeight), chartInset, radiusIconDivider); + mRenderer = new IconPieChartRenderer(this, mAnimator, mViewPortHandler, getResources(), new PointF(iconWidth, iconHeight), radiusIconDivider, circleRadius, circleWidth); } } diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java index 36cbf52f1a..e389a46b73 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/IconPieChartRenderer.java @@ -22,8 +22,9 @@ import java.util.List; public class IconPieChartRenderer extends PieChartRenderer { - private final float mChartInset; private final float mRadiusIconDivider; + private final float mCircleRadius; + private final float mCircleWidth; protected IconPieChart mChart; private final Resources mResources; @@ -32,14 +33,17 @@ public class IconPieChartRenderer extends PieChartRenderer { private int mIconXOffset; private int mIconYOffset; - public IconPieChartRenderer(IconPieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Resources resources, PointF iconSize, float chartInset, float radiusIconDivider) { + public IconPieChartRenderer(IconPieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler, Resources resources, PointF iconSize, float radiusIconDivider, float circleRadius, float circleWidth) { super(chart, animator, viewPortHandler); mChart = chart; mResources = resources; mIconSize = iconSize; - mChartInset = chartInset; mRadiusIconDivider = radiusIconDivider; + + mCircleRadius = circleRadius; + mCircleWidth = circleWidth; + } @Override @@ -54,7 +58,6 @@ protected void drawDataSet(Canvas c, IconPieDataSet dataSet) { float[] drawAngles = mChart.getDrawAngles(); for (int j = 0; j < dataSet.getEntryCount(); j++) { - float sliceAngle = drawAngles[j]; float sliceSpace = dataSet.getSliceSpace(); @@ -71,7 +74,9 @@ protected void drawDataSet(Canvas c, IconPieDataSet dataSet) { } RectF rectInner = new RectF(mChart.getCircleBox()); - rectInner.inset(Math.max(mIconSize.x, mIconSize.y)*mChartInset, Math.max(mIconSize.x, mIconSize.y)*mChartInset); + float centerX = rectInner.centerX(); + float centerY = rectInner.centerY(); + rectInner.set(centerX-mCircleRadius, centerY-mCircleRadius, centerX+mCircleRadius, centerY+mCircleRadius); mBitmapCanvas.drawArc(rectInner, rotationAngle + (angle + sliceSpace / 2f) * mAnimator.getPhaseY(), @@ -83,6 +88,24 @@ protected void drawDataSet(Canvas c, IconPieDataSet dataSet) { } } + /** + * draws the hole in the center of the chart and the transparent circle / + * hole + */ + protected void drawHole(Canvas c) { + if (mChart.isDrawHoleEnabled()) { + PointF center = mChart.getCenterCircleBox(); + float transparentHoleRadius = mCircleRadius - mCircleWidth; + + // draw the hole-circle + mBitmapCanvas.drawCircle(center.x, center.y, transparentHoleRadius, mHolePaint); + } + } + + public float getRadius() { + return mCircleRadius; + } + @Override public void drawValues(Canvas c) { diff --git a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java index cc26c73e18..f7607f9ea2 100644 --- a/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java +++ b/MPChartLib/src/com/github/mikephil/charting/renderer/PieChartRenderer.java @@ -301,8 +301,7 @@ protected void drawHole(Canvas c) { } // draw the hole-circle - mBitmapCanvas.drawCircle(center.x, center.y, - radius / 100 * holeRadius, mHolePaint); + mBitmapCanvas.drawCircle(center.x, center.y, radius / 100 * holeRadius, mHolePaint); } } From 0f2042ef53785eaa4c8ba97156c1c5162eab8611 Mon Sep 17 00:00:00 2001 From: Daniel Malmqvist Date: Mon, 15 Feb 2016 11:23:35 +0100 Subject: [PATCH 8/8] Fixes xlabel height issues --- .../github/mikephil/charting/utils/Utils.java | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java index b8e6cd7964..c7241b3852 100644 --- a/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java +++ b/MPChartLib/src/com/github/mikephil/charting/utils/Utils.java @@ -525,6 +525,10 @@ public static float getNormalizedAngle(float angle) { private static Rect mDrawTextRectBuffer = new Rect(); private static Paint.FontMetrics mFontMetricsBuffer = new Paint.FontMetrics(); + private static final String allChars = "abcdefghijklmnopqrstuvwxyzåäöABCDEFGHIJKLMNOPQRSTUVWXYZÅÄÖ0123456789"; + private static int allCharsHeight = -1; + private static float allCharsHeightFromTextSize = -1; + public static void drawText(Canvas c, String text, float x, float y, Paint paint, PointF anchor, float angleDegrees) { @@ -532,17 +536,19 @@ public static void drawText(Canvas c, String text, float x, float y, float drawOffsetX = 0.f; float drawOffsetY = 0.f; - paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); + if (allCharsHeight <= 0 || allCharsHeightFromTextSize != paint.getTextSize()) { + paint.getTextBounds(allChars, 0, allChars.length(), mDrawTextRectBuffer); + allCharsHeight = mDrawTextRectBuffer.height(); + allCharsHeightFromTextSize = paint.getTextSize(); + } - final float lineHeight = mDrawTextRectBuffer.height(); + final float lineHeight = allCharsHeight; + drawOffsetY += lineHeight/1.5f; - // Android sometimes has pre-padding - drawOffsetX -= mDrawTextRectBuffer.left; + paint.getTextBounds(text, 0, text.length(), mDrawTextRectBuffer); - // Android does not snap the bounds to line boundaries, - // and draws from bottom to top. - // And we want to normalize it. - drawOffsetY += lineHeight; + // Android sometimes has pre-padding + drawOffsetX -= mDrawTextRectBuffer.left; // To have a consistent point of reference, we always draw left-aligned Paint.Align originalTextAlign = paint.getTextAlign();