Skip to content

Commit 1d2853d

Browse files
Mohini Katarahannesa2
authored andcommitted
Added RoundedBarChartRenderer & RoundedHorizontalBarChartRenderer for corner radius positive/negative Bar Chart
1 parent 3bc65ad commit 1d2853d

2 files changed

Lines changed: 566 additions & 0 deletions

File tree

Lines changed: 324 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,324 @@
1+
package com.github.mikephil.charting.renderer;
2+
3+
import android.graphics.Canvas;
4+
import android.graphics.LinearGradient;
5+
import android.graphics.Path;
6+
import android.graphics.RectF;
7+
import android.graphics.Shader;
8+
9+
import com.github.mikephil.charting.animation.ChartAnimator;
10+
import com.github.mikephil.charting.buffer.BarBuffer;
11+
import com.github.mikephil.charting.data.BarData;
12+
import com.github.mikephil.charting.data.BarEntry;
13+
import com.github.mikephil.charting.highlight.Highlight;
14+
import com.github.mikephil.charting.highlight.Range;
15+
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider;
16+
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet;
17+
import com.github.mikephil.charting.utils.Transformer;
18+
import com.github.mikephil.charting.utils.Utils;
19+
import com.github.mikephil.charting.utils.ViewPortHandler;
20+
21+
public class RoundedBarChartRenderer extends BarChartRenderer {
22+
23+
public RoundedBarChartRenderer(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
24+
super(chart, animator, viewPortHandler);
25+
}
26+
private final RectF mBarShadowRectBuffer = new RectF();
27+
private float mRadius = 20f;
28+
private float roundedShadowRadius = 0f;
29+
private float roundedPositiveDataSetRadius = 0f;
30+
private float roundedNegativeDataSetRadius = 0f;
31+
public void setRoundedNegativeDataSetRadius(float roundedNegativeDataSet) {
32+
roundedNegativeDataSetRadius = roundedNegativeDataSet;
33+
}
34+
public void setRoundedShadowRadius(float roundedShadow) {
35+
roundedShadowRadius = roundedShadow;
36+
}
37+
public void setRoundedPositiveDataSetRadius(float roundedPositiveDataSet) {
38+
roundedPositiveDataSetRadius = roundedPositiveDataSet;
39+
}
40+
41+
@Override
42+
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
43+
initBuffers();
44+
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
45+
mBarBorderPaint.setColor(dataSet.getBarBorderColor());
46+
mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth()));
47+
mShadowPaint.setColor(dataSet.getBarShadowColor());
48+
boolean drawBorder = dataSet.getBarBorderWidth() > 0f;
49+
float phaseX = mAnimator.getPhaseX();
50+
float phaseY = mAnimator.getPhaseY();
51+
52+
if (mChart.isDrawBarShadowEnabled()) {
53+
mShadowPaint.setColor(dataSet.getBarShadowColor());
54+
BarData barData = mChart.getBarData();
55+
float barWidth = barData.getBarWidth();
56+
float barWidthHalf = barWidth / 2.0f;
57+
float x;
58+
int i = 0;
59+
double count = Math.min(Math.ceil((int) (double) ((float) dataSet.getEntryCount() * phaseX)), dataSet.getEntryCount());
60+
while (i < count) {
61+
BarEntry e = dataSet.getEntryForIndex(i);
62+
x = e.getX();
63+
mBarShadowRectBuffer.left = x - barWidthHalf;
64+
mBarShadowRectBuffer.right = x + barWidthHalf;
65+
trans.rectValueToPixel(mBarShadowRectBuffer);
66+
if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) {
67+
i++;
68+
continue;
69+
}
70+
if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
71+
break;
72+
mBarShadowRectBuffer.top = mViewPortHandler.contentTop();
73+
mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom();
74+
75+
76+
if (roundedShadowRadius >0) {
77+
c.drawRoundRect(mBarRect, roundedShadowRadius, roundedShadowRadius, mShadowPaint);
78+
} else {
79+
c.drawRect(mBarShadowRectBuffer, mShadowPaint);
80+
}
81+
i++;
82+
}
83+
}
84+
85+
BarBuffer buffer = mBarBuffers[index];
86+
buffer.setPhases(phaseX, phaseY);
87+
buffer.setDataSet(index);
88+
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
89+
buffer.setBarWidth(mChart.getBarData().getBarWidth());
90+
buffer.feed(dataSet);
91+
trans.pointValuesToPixel(buffer.buffer);
92+
93+
// if multiple colors has been assigned to Bar Chart
94+
if (dataSet.getColors().size() > 1) {
95+
96+
for (int j = 0; j < buffer.size(); j += 4) {
97+
98+
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
99+
continue;
100+
101+
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
102+
break;
103+
104+
if (mChart.isDrawBarShadowEnabled()) {
105+
if (roundedShadowRadius >0)
106+
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
107+
buffer.buffer[j + 2],
108+
mViewPortHandler.contentBottom()), roundedShadowRadius, roundedShadowRadius, mShadowPaint);
109+
else
110+
c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(),
111+
buffer.buffer[j + 2],
112+
mViewPortHandler.contentBottom(), mShadowPaint);
113+
}
114+
115+
// Set the color for the currently drawn value. If the index
116+
mRenderPaint.setColor(dataSet.getColor(j / 4));
117+
118+
if (roundedPositiveDataSetRadius >0)
119+
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
120+
buffer.buffer[j + 3]), roundedPositiveDataSetRadius, roundedPositiveDataSetRadius, mRenderPaint);
121+
else
122+
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
123+
buffer.buffer[j + 3], mRenderPaint);
124+
}
125+
} else {
126+
127+
mRenderPaint.setColor(dataSet.getColor());
128+
129+
for (int j = 0; j < buffer.size(); j += 4) {
130+
131+
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
132+
continue;
133+
134+
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
135+
break;
136+
137+
if (mChart.isDrawBarShadowEnabled()) {
138+
if (roundedShadowRadius >0)
139+
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
140+
buffer.buffer[j + 2],
141+
mViewPortHandler.contentBottom()), roundedShadowRadius, roundedShadowRadius, mShadowPaint);
142+
else
143+
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
144+
buffer.buffer[j + 3], mRenderPaint);
145+
}
146+
147+
if (roundedPositiveDataSetRadius >0)
148+
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
149+
buffer.buffer[j + 3]), roundedPositiveDataSetRadius, roundedPositiveDataSetRadius, mRenderPaint);
150+
else
151+
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
152+
buffer.buffer[j + 3], mRenderPaint);
153+
}
154+
}
155+
156+
157+
boolean isSingleColor = dataSet.getColors().size() == 1;
158+
if (isSingleColor) {
159+
mRenderPaint.setColor(dataSet.getColor(index));
160+
}
161+
162+
int j = 0;
163+
while (j < buffer.size()) {
164+
165+
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) {
166+
j += 4;
167+
continue;
168+
}
169+
170+
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
171+
break;
172+
173+
if (!isSingleColor) {
174+
mRenderPaint.setColor(dataSet.getColor(j/4));
175+
}
176+
177+
mRenderPaint.setShader(new LinearGradient(
178+
buffer.buffer[j],
179+
buffer.buffer[j + 3],
180+
buffer.buffer[j],
181+
buffer.buffer[j + 1],
182+
dataSet.getColor(j/4),
183+
dataSet.getColor(j/4),
184+
Shader.TileMode.MIRROR));
185+
186+
mRenderPaint.setShader(new LinearGradient(
187+
buffer.buffer[j],
188+
buffer.buffer[j + 3],
189+
buffer.buffer[j],
190+
buffer.buffer[j + 1],
191+
dataSet.getColor(j/4),
192+
dataSet.getColor(j/4),
193+
Shader.TileMode.MIRROR));
194+
195+
196+
if((dataSet.getEntryForIndex(j/4).getY()<0 && roundedNegativeDataSetRadius >0)) {
197+
Path path2 = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
198+
buffer.buffer[j + 3]), roundedNegativeDataSetRadius, roundedNegativeDataSetRadius, true, true, true, true);
199+
c.drawPath(path2, mRenderPaint);
200+
} else if((dataSet.getEntryForIndex(j/4).getY()>0 && roundedPositiveDataSetRadius >0)){
201+
Path path2 = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
202+
buffer.buffer[j + 3]), roundedPositiveDataSetRadius, roundedPositiveDataSetRadius, true, true, true, true);
203+
c.drawPath(path2, mRenderPaint);
204+
}
205+
else {
206+
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
207+
buffer.buffer[j + 3], mRenderPaint);
208+
}
209+
210+
j += 4;
211+
}
212+
213+
}
214+
215+
@Override
216+
public void drawHighlighted(Canvas c, Highlight[] indices) {
217+
BarData barData = mChart.getBarData();
218+
219+
for (Highlight high : indices) {
220+
221+
IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
222+
223+
if (set == null || !set.isHighlightEnabled()) {
224+
continue;
225+
}
226+
227+
BarEntry e = set.getEntryForXValue(high.getX(), high.getY());
228+
229+
if (!isInBoundsX(e, set)) {
230+
continue;
231+
}
232+
233+
Transformer trans = mChart.getTransformer(set.getAxisDependency());
234+
235+
mHighlightPaint.setColor(set.getHighLightColor());
236+
mHighlightPaint.setAlpha(set.getHighLightAlpha());
237+
238+
boolean isStack = high.getStackIndex() >= 0 && e.isStacked();
239+
240+
final float y1;
241+
final float y2;
242+
243+
if (isStack) {
244+
245+
if (mChart.isHighlightFullBarEnabled()) {
246+
247+
y1 = e.getPositiveSum();
248+
y2 = -e.getNegativeSum();
249+
250+
} else {
251+
252+
Range range = e.getRanges()[high.getStackIndex()];
253+
254+
y1 = range.from;
255+
y2 = range.to;
256+
}
257+
258+
} else {
259+
y1 = e.getY();
260+
y2 = 0.f;
261+
}
262+
263+
prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
264+
265+
setHighlightDrawPos(high, mBarRect);
266+
267+
Path path2 = roundRect(new RectF(mBarRect.left, mBarRect.top, mBarRect.right,
268+
mBarRect.bottom), mRadius, mRadius, true, true, true, true);
269+
270+
c.drawPath(path2, mHighlightPaint);
271+
}
272+
}
273+
274+
private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
275+
float top = rect.top;
276+
float left = rect.left;
277+
float right = rect.right;
278+
float bottom = rect.bottom;
279+
Path path = new Path();
280+
if (rx < 0) rx = 0;
281+
if (ry < 0) ry = 0;
282+
float width = right - left;
283+
float height = bottom - top;
284+
if (rx > width / 2) rx = width / 2;
285+
if (ry > height / 2) ry = height / 2;
286+
float widthMinusCorners = (width - (2 * rx));
287+
float heightMinusCorners = (height - (2 * ry));
288+
289+
path.moveTo(right, top + ry);
290+
if (tr)
291+
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
292+
else {
293+
path.rLineTo(0, -ry);
294+
path.rLineTo(-rx, 0);
295+
}
296+
path.rLineTo(-widthMinusCorners, 0);
297+
if (tl)
298+
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
299+
else {
300+
path.rLineTo(-rx, 0);
301+
path.rLineTo(0, ry);
302+
}
303+
path.rLineTo(0, heightMinusCorners);
304+
305+
if (bl)
306+
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
307+
else {
308+
path.rLineTo(0, ry);
309+
path.rLineTo(rx, 0);
310+
}
311+
312+
path.rLineTo(widthMinusCorners, 0);
313+
if (br)
314+
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
315+
else {
316+
path.rLineTo(rx, 0);
317+
path.rLineTo(0, -ry);
318+
}
319+
320+
path.rLineTo(0, -heightMinusCorners);
321+
path.close();
322+
return path;
323+
}
324+
}

0 commit comments

Comments
 (0)