Implemented icon support

This commit is contained in:
Daniel Cohen Gindi 2017-02-20 13:33:39 +02:00
parent ccf6b7e3b1
commit a02e108f46
20 changed files with 708 additions and 86 deletions

View file

@ -1,6 +1,7 @@
package com.github.mikephil.charting.data;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.highlight.Range;
@ -32,20 +33,6 @@ public class BarEntry extends Entry {
*/
private float mPositiveSum;
/**
* Constructor for stacked bar entries.
*
* @param x
* @param vals - the stack values, use at lest 2
*/
public BarEntry(float x, float[] vals) {
super(x, calcSum(vals));
this.mYVals = vals;
calcPosNegSum();
calcRanges();
}
/**
* Constructor for normal bars (not stacked).
*
@ -57,18 +44,14 @@ public class BarEntry extends Entry {
}
/**
* Constructor for stacked bar entries.
* Constructor for normal bars (not stacked).
*
* @param x
* @param vals - the stack values, use at least 2
* @param label Additional description label.
* @param y
* @param data - Spot for additional data this Entry represents.
*/
public BarEntry(float x, float[] vals, String label) {
super(x, calcSum(vals), label);
this.mYVals = vals;
calcPosNegSum();
calcRanges();
public BarEntry(float x, float y, Object data) {
super(x, y, data);
}
/**
@ -76,10 +59,82 @@ public class BarEntry extends Entry {
*
* @param x
* @param y
* @param data Spot for additional data this Entry represents.
* @param icon - icon image
*/
public BarEntry(float x, float y, Object data) {
super(x, y, data);
public BarEntry(float x, float y, Drawable icon) {
super(x, y, icon);
}
/**
* Constructor for normal bars (not stacked).
*
* @param x
* @param y
* @param icon - icon image
* @param data - Spot for additional data this Entry represents.
*/
public BarEntry(float x, float y, Drawable icon, Object data) {
super(x, y, icon, data);
}
/**
* Constructor for stacked bar entries. One data object for whole stack
*
* @param x
* @param vals - the stack values, use at least 2
*/
public BarEntry(float x, float[] vals) {
super(x, calcSum(vals));
this.mYVals = vals;
calcPosNegSum();
calcRanges();
}
/**
* Constructor for stacked bar entries. One data object for whole stack
*
* @param x
* @param vals - the stack values, use at least 2
* @param data - Spot for additional data this Entry represents.
*/
public BarEntry(float x, float[] vals, Object data) {
super(x, calcSum(vals), data);
this.mYVals = vals;
calcPosNegSum();
calcRanges();
}
/**
* Constructor for stacked bar entries. One data object for whole stack
*
* @param x
* @param vals - the stack values, use at least 2
* @param icon - icon image
*/
public BarEntry(float x, float[] vals, Drawable icon) {
super(x, calcSum(vals), icon);
this.mYVals = vals;
calcPosNegSum();
calcRanges();
}
/**
* Constructor for stacked bar entries. One data object for whole stack
*
* @param x
* @param vals - the stack values, use at least 2
* @param icon - icon image
* @param data - Spot for additional data this Entry represents.
*/
public BarEntry(float x, float[] vals, Drawable icon, Object data) {
super(x, calcSum(vals), icon, data);
this.mYVals = vals;
calcPosNegSum();
calcRanges();
}
/**

View file

@ -11,8 +11,11 @@ import com.github.mikephil.charting.formatter.DefaultValueFormatter;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.interfaces.datasets.IDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Utils;
import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.util.ArrayList;
import java.util.List;
@ -68,6 +71,16 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
*/
protected boolean mDrawValues = true;
/**
* if true, y-icons are drawn on the chart
*/
protected boolean mDrawIcons = true;
/**
* the offset for drawing icons (in dp)
*/
protected MPPointF mIconsOffset = new MPPointF();
/**
* the size of the value-text labels
*/
@ -371,6 +384,28 @@ public abstract class BaseDataSet<T extends Entry> implements IDataSet<T> {
return mDrawValues;
}
@Override
public void setDrawIcons(boolean enabled) {
mDrawIcons = enabled;
}
@Override
public boolean isDrawIconsEnabled() {
return mDrawIcons;
}
@Override
public void setIconsOffset(MPPointF offsetDp) {
mIconsOffset.x = offsetDp.x;
mIconsOffset.y = offsetDp.y;
}
@Override
public MPPointF getIconsOffset() {
return mIconsOffset;
}
@Override
public void setVisible(boolean visible) {
mVisible = visible;

View file

@ -1,5 +1,7 @@
package com.github.mikephil.charting.data;
import android.graphics.drawable.Drawable;
/**
* Created by Philipp Jahoda on 02/06/16.
*/
@ -11,6 +13,9 @@ public abstract class BaseEntry {
/** optional spot for additional data this Entry represents */
private Object mData = null;
/** optional icon image */
private Drawable mIcon = null;
public BaseEntry() {
}
@ -24,6 +29,17 @@ public abstract class BaseEntry {
this.mData = data;
}
public BaseEntry(float y, Drawable icon) {
this(y);
this.mIcon = icon;
}
public BaseEntry(float y, Drawable icon, Object data) {
this(y);
this.mIcon = icon;
this.mData = data;
}
/**
* Returns the y value of this Entry.
*
@ -33,6 +49,24 @@ public abstract class BaseEntry {
return y;
}
/**
* Sets the icon drawable
*
* @param icon
*/
public void setIcon(Drawable icon) {
this.mIcon = icon;
}
/**
* Returns the icon of this Entry.
*
* @return
*/
public Drawable getIcon() {
return mIcon;
}
/**
* Sets the y-value for the Entry.
*

View file

@ -2,6 +2,7 @@
package com.github.mikephil.charting.data;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
/**
* Subclass of Entry that holds a value for one entry in a BubbleChart. Bubble
@ -41,6 +42,33 @@ public class BubbleEntry extends Entry {
this.mSize = size;
}
/**
* Constructor.
*
* @param x The value on the x-axis.
* @param y The value on the y-axis.
* @param size The size of the bubble.
* @param icon Icon image
*/
public BubbleEntry(float x, float y, float size, Drawable icon) {
super(x, y, icon);
this.mSize = size;
}
/**
* Constructor.
*
* @param x The value on the x-axis.
* @param y The value on the y-axis.
* @param size The size of the bubble.
* @param icon Icon image
* @param data Spot for additional data this Entry represents.
*/
public BubbleEntry(float x, float y, float size, Drawable icon, Object data) {
super(x, y, icon, data);
this.mSize = size;
}
public BubbleEntry copy() {
BubbleEntry c = new BubbleEntry(getX(), getY(), mSize, getData());

View file

@ -2,6 +2,7 @@
package com.github.mikephil.charting.data;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
/**
* Subclass of Entry that holds all values for one entry in a CandleStickChart.
@ -26,11 +27,11 @@ public class CandleEntry extends Entry {
/**
* Constructor.
*
* @param x The value on the x-axis.
* @param shadowH The (shadow) high value.
* @param shadowL The (shadow) low value.
* @param open The open value.
* @param close The close value.
* @param x The value on the x-axis
* @param shadowH The (shadow) high value
* @param shadowL The (shadow) low value
* @param open The open value
* @param close The close value
*/
public CandleEntry(float x, float shadowH, float shadowL, float open, float close) {
super(x, (shadowH + shadowL) / 2f);
@ -43,16 +44,16 @@ public class CandleEntry extends Entry {
/**
* Constructor.
*
* @param x The value on the x-axis.
* @param shadowH The (shadow) high value.
* @param shadowL The (shadow) low value.
*
* @param x The value on the x-axis
* @param shadowH The (shadow) high value
* @param shadowL The (shadow) low value
* @param open
* @param close
* @param data Spot for additional data this Entry represents.
* @param data Spot for additional data this Entry represents
*/
public CandleEntry(float x, float shadowH, float shadowL, float open, float close,
Object data) {
Object data) {
super(x, (shadowH + shadowL) / 2f, data);
this.mShadowHigh = shadowH;
@ -61,6 +62,47 @@ public class CandleEntry extends Entry {
this.mClose = close;
}
/**
* Constructor.
*
* @param x The value on the x-axis
* @param shadowH The (shadow) high value
* @param shadowL The (shadow) low value
* @param open
* @param close
* @param icon Icon image
*/
public CandleEntry(float x, float shadowH, float shadowL, float open, float close,
Drawable icon) {
super(x, (shadowH + shadowL) / 2f, icon);
this.mShadowHigh = shadowH;
this.mShadowLow = shadowL;
this.mOpen = open;
this.mClose = close;
}
/**
* Constructor.
*
* @param x The value on the x-axis
* @param shadowH The (shadow) high value
* @param shadowL The (shadow) low value
* @param open
* @param close
* @param icon Icon image
* @param data Spot for additional data this Entry represents
*/
public CandleEntry(float x, float shadowH, float shadowL, float open, float close,
Drawable icon, Object data) {
super(x, (shadowH + shadowL) / 2f, icon, data);
this.mShadowHigh = shadowH;
this.mShadowLow = shadowL;
this.mOpen = open;
this.mClose = close;
}
/**
* Returns the overall range (difference) between shadow-high and
* shadow-low.

View file

@ -1,6 +1,7 @@
package com.github.mikephil.charting.data;
import android.graphics.drawable.Drawable;
import android.os.Parcel;
import android.os.ParcelFormatException;
import android.os.Parcelable;
@ -45,6 +46,31 @@ public class Entry extends BaseEntry implements Parcelable {
this.x = x;
}
/**
* A Entry represents one single entry in the chart.
*
* @param x the x value
* @param y the y value (the actual value of the entry)
* @param icon icon image
*/
public Entry(float x, float y, Drawable icon) {
super(y, icon);
this.x = x;
}
/**
* A Entry represents one single entry in the chart.
*
* @param x the x value
* @param y the y value (the actual value of the entry)
* @param icon icon image
* @param data Spot for additional data this Entry represents.
*/
public Entry(float x, float y, Drawable icon, Object data) {
super(y, icon, data);
this.x = x;
}
/**
* Returns the x-value of this Entry object.
*

View file

@ -1,10 +1,11 @@
package com.github.mikephil.charting.data;
import android.annotation.SuppressLint;
import android.graphics.drawable.Drawable;
import android.util.Log;
/**
* Created by Philipp Jahoda on 31/05/16.
* @author Philipp Jahoda
*/
@SuppressLint("ParcelCreator")
public class PieEntry extends Entry {
@ -19,6 +20,14 @@ public class PieEntry extends Entry {
super(0f, value, data);
}
public PieEntry(float value, Drawable icon) {
super(0f, value, icon);
}
public PieEntry(float value, Drawable icon, Object data) {
super(0f, value, icon, data);
}
public PieEntry(float value, String label) {
super(0f, value);
this.label = label;
@ -29,6 +38,16 @@ public class PieEntry extends Entry {
this.label = label;
}
public PieEntry(float value, String label, Drawable icon) {
super(0f, value, icon);
this.label = label;
}
public PieEntry(float value, String label, Drawable icon, Object data) {
super(0f, value, icon, data);
this.label = label;
}
/**
* This is the same as getY(). Returns the value of the PieEntry.
*

View file

@ -1,6 +1,7 @@
package com.github.mikephil.charting.interfaces.datasets;
import android.graphics.DashPathEffect;
import android.graphics.PointF;
import android.graphics.Typeface;
import com.github.mikephil.charting.components.Legend;
@ -8,6 +9,7 @@ import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.DataSet;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.utils.MPPointF;
import java.util.List;
@ -419,10 +421,10 @@ public interface IDataSet<T extends Entry> {
DashPathEffect getFormLineDashEffect();
/**
* set this to true to draw y-values on the chart NOTE (for bar and
* linechart): if "maxvisiblecount" is reached, no values will be drawn even
* if this is enabled
* set this to true to draw y-values on the chart.
*
* NOTE (for bar and line charts): if `maxVisibleCount` is reached, no values will be drawn even
* if this is enabled
* @param enabled
*/
void setDrawValues(boolean enabled);
@ -434,6 +436,38 @@ public interface IDataSet<T extends Entry> {
*/
boolean isDrawValuesEnabled();
/**
* Set this to true to draw y-icons on the chart.
*
* NOTE (for bar and line charts): if `maxVisibleCount` is reached, no icons will be drawn even
* if this is enabled
*
* @param enabled
*/
void setDrawIcons(boolean enabled);
/**
* Returns true if y-icon drawing is enabled, false if not
*
* @return
*/
boolean isDrawIconsEnabled();
/**
* Offset of icons drawn on the chart.
*
* For all charts except Pie and Radar it will be ordinary (x offset,y offset).
*
* For Pie and Radar chart it will be (y offset, distance from center offset); so if you want icon to be rendered under value, you should increase X component of CGPoint, and if you want icon to be rendered closet to center, you should decrease height component of CGPoint.
* @param offset
*/
void setIconsOffset(MPPointF offset);
/**
* Get the offset for drawing icons.
*/
MPPointF getIconsOffset();
/**
* Set the visibility of this DataSet. If not visible, the DataSet will not
* be drawn to the chart upon refreshing it.

View file

@ -5,6 +5,7 @@ import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.buffer.BarBuffer;
@ -14,6 +15,7 @@ import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.highlight.Range;
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
@ -224,6 +226,10 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer {
final float phaseY = mAnimator.getPhaseY();
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
// if only single values are drawn (sum)
if (!dataSet.isStacked()) {
@ -241,9 +247,34 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer {
BarEntry entry = dataSet.getEntryForIndex(j / 4);
float val = entry.getY();
drawValue(c, dataSet.getValueFormatter(), val, entry, i, x,
val >= 0 ? (buffer.buffer[j + 1] + posOffset) : (buffer.buffer[j + 3] + negOffset),
dataSet.getValueTextColor(j / 4));
if (dataSet.isDrawValuesEnabled()) {
drawValue(c, dataSet.getValueFormatter(), val, entry, i, x,
val >= 0 ?
(buffer.buffer[j + 1] + posOffset) :
(buffer.buffer[j + 3] + negOffset),
dataSet.getValueTextColor(j / 4));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
float px = x;
float py = val >= 0 ?
(buffer.buffer[j + 1] + posOffset) :
(buffer.buffer[j + 3] + negOffset);
px += iconsOffset.x;
py += iconsOffset.y;
Utils.drawImage(
c,
icon,
(int)px,
(int)py,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
// if we have stacks
@ -275,9 +306,32 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer {
|| !mViewPortHandler.isInBoundsLeft(x))
continue;
drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x,
buffer.buffer[bufferIndex + 1] + (entry.getY() >= 0 ? posOffset : negOffset),
color);
if (dataSet.isDrawValuesEnabled()) {
drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x,
buffer.buffer[bufferIndex + 1] +
(entry.getY() >= 0 ? posOffset : negOffset),
color);
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
float px = x;
float py = buffer.buffer[bufferIndex + 1] +
(entry.getY() >= 0 ? posOffset : negOffset);
px += iconsOffset.x;
py += iconsOffset.y;
Utils.drawImage(
c,
icon,
(int)px,
(int)py,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
// draw stack values
} else {
@ -324,7 +378,29 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer {
|| !mViewPortHandler.isInBoundsLeft(x))
continue;
drawValue(c, dataSet.getValueFormatter(), vals[k / 2], entry, i, x, y, color);
if (dataSet.isDrawValuesEnabled()) {
drawValue(c,
dataSet.getValueFormatter(),
vals[k / 2],
entry,
i,
x,
y,
color);
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.drawImage(
c,
icon,
(int)(x + iconsOffset.x),
(int)(y + iconsOffset.y),
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
}
@ -332,6 +408,8 @@ public class BarChartRenderer extends BarLineScatterCandleBubbleRenderer {
index++;
}
}
MPPointF.recycleInstance(iconsOffset);
}
}
}

View file

@ -29,7 +29,7 @@ public abstract class BarLineScatterCandleBubbleRenderer extends DataRenderer {
* @return
*/
protected boolean shouldDrawValues(IDataSet set) {
return set.isVisible() && set.isDrawValuesEnabled();
return set.isVisible() && (set.isDrawValuesEnabled() || set.isDrawIconsEnabled());
}
/**

View file

@ -4,6 +4,7 @@ package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.data.BubbleData;
@ -11,6 +12,7 @@ import com.github.mikephil.charting.data.BubbleEntry;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.dataprovider.BubbleDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IBubbleDataSet;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
@ -145,6 +147,10 @@ public class BubbleChartRenderer extends BarLineScatterCandleBubbleRenderer {
final float alpha = phaseX == 1 ? phaseY : phaseX;
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
for (int j = 0; j < positions.length; j += 2) {
int valueTextColor = dataSet.getValueTextColor(j / 2 + mXBounds.min);
@ -162,9 +168,26 @@ public class BubbleChartRenderer extends BarLineScatterCandleBubbleRenderer {
BubbleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min);
drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x,
y + (0.5f * lineHeight), valueTextColor);
if (dataSet.isDrawValuesEnabled()) {
drawValue(c, dataSet.getValueFormatter(), entry.getSize(), entry, i, x,
y + (0.5f * lineHeight), valueTextColor);
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.drawImage(
c,
icon,
(int)(x + iconsOffset.x),
(int)(y + iconsOffset.y),
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
MPPointF.recycleInstance(iconsOffset);
}
}
}

View file

@ -3,6 +3,7 @@ package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.data.CandleData;
@ -12,6 +13,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.CandleDataProvider;
import com.github.mikephil.charting.interfaces.datasets.ICandleDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.MPPointD;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
@ -277,6 +279,10 @@ public class CandleStickChartRenderer extends LineScatterCandleRadarRenderer {
float yOffset = Utils.convertDpToPixel(5f);
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
for (int j = 0; j < positions.length; j += 2) {
float x = positions[j];
@ -290,9 +296,33 @@ public class CandleStickChartRenderer extends LineScatterCandleRadarRenderer {
CandleEntry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min);
drawValue(c, dataSet.getValueFormatter(), entry.getHigh(), entry, i, x, y - yOffset, dataSet
.getValueTextColor(j / 2));
if (dataSet.isDrawValuesEnabled()) {
drawValue(c,
dataSet.getValueFormatter(),
entry.getHigh(),
entry,
i,
x,
y - yOffset,
dataSet
.getValueTextColor(j / 2));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.drawImage(
c,
icon,
(int)(x + iconsOffset.x),
(int)(y + iconsOffset.y),
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
MPPointF.recycleInstance(iconsOffset);
}
}
}

View file

@ -6,6 +6,7 @@ import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.data.Entry;
@ -13,6 +14,7 @@ import com.github.mikephil.charting.formatter.IValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface;
import com.github.mikephil.charting.interfaces.datasets.IDataSet;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;

View file

@ -4,6 +4,7 @@ package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.Paint.Align;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.buffer.BarBuffer;
@ -15,6 +16,7 @@ import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
import com.github.mikephil.charting.interfaces.dataprovider.ChartInterface;
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
@ -172,6 +174,10 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
final float phaseY = mAnimator.getPhaseY();
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
// if only single values are drawn (sum)
if (!dataSet.isStacked()) {
@ -188,9 +194,9 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[j + 1]))
continue;
BarEntry e = dataSet.getEntryForIndex(j / 4);
float val = e.getY();
String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler);
BarEntry entry = dataSet.getEntryForIndex(j / 4);
float val = entry.getY();
String formattedValue = formatter.getFormattedValue(val, entry, i, mViewPortHandler);
// calculate the correct offset depending on the draw position of the value
float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue);
@ -202,8 +208,32 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
negOffset = -negOffset - valueTextWidth;
}
drawValue(c, formattedValue, buffer.buffer[j + 2] + (val >= 0 ? posOffset : negOffset),
y + halfTextHeight, dataSet.getValueTextColor(j / 2));
if (dataSet.isDrawValuesEnabled()) {
drawValue(c,
formattedValue,
buffer.buffer[j + 2] + (val >= 0 ? posOffset : negOffset),
y + halfTextHeight,
dataSet.getValueTextColor(j / 2));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
float px = buffer.buffer[j + 2] + (val >= 0 ? posOffset : negOffset);
float py = y;
px += iconsOffset.x;
py += iconsOffset.y;
Utils.drawImage(
c,
icon,
(int)px,
(int)py,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
// if each value of a potential stack should be drawn
@ -216,10 +246,10 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
while (index < dataSet.getEntryCount() * mAnimator.getPhaseX()) {
BarEntry e = dataSet.getEntryForIndex(index);
BarEntry entry = dataSet.getEntryForIndex(index);
int color = dataSet.getValueTextColor(index);
float[] vals = e.getYVals();
float[] vals = entry.getYVals();
// we still draw stacked bars, but there is one
// non-stacked
@ -235,8 +265,9 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
if (!mViewPortHandler.isInBoundsBottom(buffer.buffer[bufferIndex + 1]))
continue;
float val = e.getY();
String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler);
float val = entry.getY();
String formattedValue = formatter.getFormattedValue(val,
entry, i, mViewPortHandler);
// calculate the correct offset depending on the draw position of the value
float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue);
@ -248,16 +279,39 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
negOffset = -negOffset - valueTextWidth;
}
drawValue(c, formattedValue, buffer.buffer[bufferIndex + 2]
+ (e.getY() >= 0 ? posOffset : negOffset),
buffer.buffer[bufferIndex + 1] + halfTextHeight, color);
if (dataSet.isDrawValuesEnabled()) {
drawValue(c, formattedValue,
buffer.buffer[bufferIndex + 2]
+ (entry.getY() >= 0 ? posOffset : negOffset),
buffer.buffer[bufferIndex + 1] + halfTextHeight, color);
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
float px = buffer.buffer[bufferIndex + 2]
+ (entry.getY() >= 0 ? posOffset : negOffset);
float py = buffer.buffer[bufferIndex + 1];
px += iconsOffset.x;
py += iconsOffset.y;
Utils.drawImage(
c,
icon,
(int)px,
(int)py,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
} else {
float[] transformed = new float[vals.length * 2];
float posY = 0f;
float negY = -e.getNegativeSum();
float negY = -entry.getNegativeSum();
for (int k = 0, idx = 0; k < transformed.length; k += 2, idx++) {
@ -283,7 +337,8 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
for (int k = 0; k < transformed.length; k += 2) {
final float val = vals[k / 2];
String formattedValue = formatter.getFormattedValue(val, e, i, mViewPortHandler);
String formattedValue = formatter.getFormattedValue(val,
entry, i, mViewPortHandler);
// calculate the correct offset depending on the draw position of the value
float valueTextWidth = Utils.calcTextWidth(mValuePaint, formattedValue);
@ -312,7 +367,22 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
if (!mViewPortHandler.isInBoundsBottom(y))
continue;
drawValue(c, formattedValue, x, y + halfTextHeight, color);
if (dataSet.isDrawValuesEnabled()) {
drawValue(c, formattedValue, x, y + halfTextHeight, color);
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.drawImage(
c,
icon,
(int)(x + iconsOffset.x),
(int)(y + iconsOffset.y),
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
}
@ -320,6 +390,8 @@ public class HorizontalBarChartRenderer extends BarChartRenderer {
index++;
}
}
MPPointF.recycleInstance(iconsOffset);
}
}
}

View file

@ -18,7 +18,9 @@ import com.github.mikephil.charting.interfaces.datasets.IDataSet;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.utils.ColorTemplate;
import com.github.mikephil.charting.utils.MPPointD;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
import java.lang.ref.WeakReference;
@ -545,6 +547,10 @@ public class LineChartRenderer extends LineRadarRenderer {
float[] positions = trans.generateTransformedValuesLine(dataSet, mAnimator.getPhaseX(), mAnimator
.getPhaseY(), mXBounds.min, mXBounds.max);
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
for (int j = 0; j < positions.length; j += 2) {
float x = positions[j];
@ -558,9 +564,26 @@ public class LineChartRenderer extends LineRadarRenderer {
Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min);
drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x,
y - valOffset, dataSet.getValueTextColor(j / 2));
if (dataSet.isDrawValuesEnabled()) {
drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, x,
y - valOffset, dataSet.getValueTextColor(j / 2));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.drawImage(
c,
icon,
(int)(x + iconsOffset.x),
(int)(y + iconsOffset.y),
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
MPPointF.recycleInstance(iconsOffset);
}
}
}

View file

@ -9,6 +9,7 @@ import android.graphics.Paint.Align;
import android.graphics.Paint.Style;
import android.graphics.Path;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Layout;
import android.text.StaticLayout;
@ -444,6 +445,10 @@ public class PieChartRenderer extends DataRenderer {
final float sliceSpace = getSliceSpace(dataSet);
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
for (int j = 0; j < entryCount; j++) {
PieEntry entry = dataSet.getEntryForIndex(j);
@ -588,8 +593,27 @@ public class PieChartRenderer extends DataRenderer {
}
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
float x = (labelRadius + iconsOffset.y) * sliceXBase + center.x;
float y = (labelRadius + iconsOffset.y) * sliceYBase + center.y;
y += iconsOffset.x;
Utils.drawImage(
c,
icon,
(int)x,
(int)y,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
xIndex++;
}
MPPointF.recycleInstance(iconsOffset);
}
MPPointF.recycleInstance(center);
c.restore();

View file

@ -160,6 +160,7 @@ public class RadarChartRenderer extends LineRadarRenderer {
MPPointF center = mChart.getCenterOffsets();
MPPointF pOut = MPPointF.getInstance(0,0);
MPPointF pIcon = MPPointF.getInstance(0,0);
float yoffset = Utils.convertDpToPixel(5f);
@ -173,6 +174,10 @@ public class RadarChartRenderer extends LineRadarRenderer {
// apply the text-styling defined by the DataSet
applyValueTextStyle(dataSet);
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
for (int j = 0; j < dataSet.getEntryCount(); j++) {
RadarEntry entry = dataSet.getEntryForIndex(j);
@ -183,13 +188,47 @@ public class RadarChartRenderer extends LineRadarRenderer {
sliceangle * j * phaseX + mChart.getRotationAngle(),
pOut);
drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, pOut.x, pOut.y - yoffset, dataSet.getValueTextColor
(j));
if (dataSet.isDrawValuesEnabled()) {
drawValue(c,
dataSet.getValueFormatter(),
entry.getY(),
entry,
i,
pOut.x,
pOut.y - yoffset,
dataSet.getValueTextColor
(j));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.getPosition(
center,
(entry.getY()) * factor * phaseY + iconsOffset.y,
sliceangle * j * phaseX + mChart.getRotationAngle(),
pIcon);
//noinspection SuspiciousNameCombination
pIcon.y += iconsOffset.x;
Utils.drawImage(
c,
icon,
(int)pIcon.x,
(int)pIcon.y,
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
MPPointF.recycleInstance(iconsOffset);
}
MPPointF.recycleInstance(center);
MPPointF.recycleInstance(pOut);
MPPointF.recycleInstance(pIcon);
}
@Override

View file

@ -2,6 +2,7 @@
package com.github.mikephil.charting.renderer;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import android.util.Log;
import com.github.mikephil.charting.animation.ChartAnimator;
@ -12,6 +13,7 @@ import com.github.mikephil.charting.interfaces.dataprovider.ScatterDataProvider;
import com.github.mikephil.charting.interfaces.datasets.IScatterDataSet;
import com.github.mikephil.charting.renderer.scatter.IShapeRenderer;
import com.github.mikephil.charting.utils.MPPointD;
import com.github.mikephil.charting.utils.MPPointF;
import com.github.mikephil.charting.utils.Transformer;
import com.github.mikephil.charting.utils.Utils;
import com.github.mikephil.charting.utils.ViewPortHandler;
@ -113,6 +115,10 @@ public class ScatterChartRenderer extends LineScatterCandleRadarRenderer {
float shapeSize = Utils.convertDpToPixel(dataSet.getScatterShapeSize());
MPPointF iconsOffset = MPPointF.getInstance(dataSet.getIconsOffset());
iconsOffset.x = Utils.convertDpToPixel(iconsOffset.x);
iconsOffset.y = Utils.convertDpToPixel(iconsOffset.y);
for (int j = 0; j < positions.length; j += 2) {
if (!mViewPortHandler.isInBoundsRight(positions[j]))
@ -125,9 +131,32 @@ public class ScatterChartRenderer extends LineScatterCandleRadarRenderer {
Entry entry = dataSet.getEntryForIndex(j / 2 + mXBounds.min);
drawValue(c, dataSet.getValueFormatter(), entry.getY(), entry, i, positions[j],
positions[j + 1] - shapeSize, dataSet.getValueTextColor(j / 2 + mXBounds.min));
if (dataSet.isDrawValuesEnabled()) {
drawValue(c,
dataSet.getValueFormatter(),
entry.getY(),
entry,
i,
positions[j],
positions[j + 1] - shapeSize,
dataSet.getValueTextColor(j / 2 + mXBounds.min));
}
if (entry.getIcon() != null && dataSet.isDrawIconsEnabled()) {
Drawable icon = entry.getIcon();
Utils.drawImage(
c,
icon,
(int)(positions[j] + iconsOffset.x),
(int)(positions[j + 1] + iconsOffset.y),
icon.getIntrinsicWidth(),
icon.getIntrinsicHeight());
}
}
MPPointF.recycleInstance(iconsOffset);
}
}
}

View file

@ -35,6 +35,17 @@ public class MPPointF extends ObjectPool.Poolable {
return result;
}
public static MPPointF getInstance() {
return pool.get();
}
public static MPPointF getInstance(MPPointF copy) {
MPPointF result = pool.get();
result.x = copy.x;
result.y = copy.y;
return result;
}
public static void recycleInstance(MPPointF instance){
pool.recycle(instance);
}

View file

@ -7,12 +7,15 @@ import android.content.res.Resources;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Build;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;
import android.util.DisplayMetrics;
import android.util.Log;
import android.util.SizeF;
import android.view.MotionEvent;
import android.view.VelocityTracker;
import android.view.View;
@ -107,14 +110,9 @@ public abstract class Utils {
" calling Utils.convertDpToPixel(...). Otherwise conversion does not " +
"take place.");
return dp;
// throw new IllegalStateException(
// "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before
// calling Utils.convertDpToPixel(...).");
}
DisplayMetrics metrics = mMetrics;
float px = dp * (metrics.densityDpi / 160f);
return px;
return dp * mMetrics.density;
}
/**
@ -133,14 +131,9 @@ public abstract class Utils {
" calling Utils.convertPixelsToDp(...). Otherwise conversion does not" +
" take place.");
return px;
// throw new IllegalStateException(
// "Utils NOT INITIALIZED. You need to call Utils.init(...) at least once before
// calling Utils.convertPixelsToDp(...).");
}
DisplayMetrics metrics = mMetrics;
float dp = px / (metrics.densityDpi / 160f);
return dp;
return px / mMetrics.density;
}
/**
@ -532,6 +525,31 @@ public abstract class Utils {
return angle % 360.f;
}
private static Rect mDrawableBoundsCache = new Rect();
public static void drawImage(Canvas canvas,
Drawable drawable,
int x, int y,
int width, int height) {
MPPointF drawOffset = MPPointF.getInstance();
drawOffset.x = x - (width / 2);
drawOffset.y = y - (height / 2);
drawable.copyBounds(mDrawableBoundsCache);
drawable.setBounds(
mDrawableBoundsCache.left,
mDrawableBoundsCache.top,
mDrawableBoundsCache.left + width,
mDrawableBoundsCache.top + width);
int saveId = canvas.save();
// translate to the correct position and draw
canvas.translate(drawOffset.x, drawOffset.y);
drawable.draw(canvas);
canvas.restoreToCount(saveId);
}
private static Rect mDrawTextRectBuffer = new Rect();
private static Paint.FontMetrics mFontMetricsBuffer = new Paint.FontMetrics();