Add option to set minimum angles

Allows to force minimum slice angles when drawing charts, which means that any
slices with angles lower than the minimum will be drawn with the minimum angle.

When changing this setting on the fly, you have to call
`notifyDataSetChanged()` and `invalidate()` for the minimum angle to take
effect.

This only functions if all slices can be drawn with the minimum angle. For
example if a chart has 5 slices, the largest functioning minimum angle is
`72f` degrees on a 360 degree chart, or 20% of the chart's `maxAngle`.
This commit is contained in:
almic 2018-11-15 09:51:46 -07:00
parent 42cdba535f
commit aea2ff3417
No known key found for this signature in database
GPG key ID: 432BBCA8E2FFF871
5 changed files with 88 additions and 1 deletions

View file

@ -210,6 +210,15 @@ public class PieChartActivity extends DemoBase implements OnSeekBarChangeListene
chart.invalidate();
break;
}
case R.id.actionToggleMinAngles: {
if (chart.getMinAngleForSlices() == 0f)
chart.setMinAngleForSlices(36f);
else
chart.setMinAngleForSlices(0f);
chart.notifyDataSetChanged();
chart.invalidate();
break;
}
case R.id.actionToggleCurvedSlices: {
boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled();
chart.setDrawRoundedSlices(toSet);

View file

@ -205,6 +205,15 @@ public class PiePolylineChartActivity extends DemoBase implements OnSeekBarChang
chart.invalidate();
break;
}
case R.id.actionToggleMinAngles: {
if (chart.getMinAngleForSlices() == 0f)
chart.setMinAngleForSlices(36f);
else
chart.setMinAngleForSlices(0f);
chart.notifyDataSetChanged();
chart.invalidate();
break;
}
case R.id.actionToggleCurvedSlices: {
boolean toSet = !chart.isDrawRoundedSlicesEnabled() || !chart.isDrawHoleEnabled();
chart.setDrawRoundedSlices(toSet);

View file

@ -21,6 +21,10 @@
android:id="@+id/actionTogglePercent"
android:title="@string/actionTogglePercent">
</item>
<item
android:id="@+id/actionToggleMinAngles"
android:title="@string/actionToggleMinAngles">
</item>
<item
android:id="@+id/actionToggleHole"
android:title="@string/actionToggleHole">

View file

@ -40,6 +40,7 @@
<string name="actionClearChart">Clear chart</string>
<string name="actionTogglePercent">Toggle Percent</string>
<string name="actionToggleMinAngles">Toggle Minimum Angles</string>
<string name="actionToggleHole">Toggle Hole</string>
<string name="actionToggleCurvedSlices">Toggle Curved Slices</string>
<string name="actionDrawCenterText">Draw Center Text</string>

View file

@ -94,6 +94,12 @@ public class PieChart extends PieRadarChartBase<PieData> {
protected float mMaxAngle = 360f;
/**
* Minimum angle to draw slices, this only works if there is enough room for all slices to have
* the minimum angle, default 0f.
*/
private float mMinAngleForSlices = 0f;
public PieChart(Context context) {
super(context);
}
@ -228,7 +234,12 @@ public class PieChart extends PieRadarChartBase<PieData> {
List<IPieDataSet> dataSets = mData.getDataSets();
boolean hasMinAngle = mMinAngleForSlices != 0f && entryCount * mMinAngleForSlices <= mMaxAngle;
float[] minAngles = new float[entryCount];
int cnt = 0;
float offset = 0f;
float diff = 0f;
for (int i = 0; i < mData.getDataSetCount(); i++) {
@ -236,7 +247,20 @@ public class PieChart extends PieRadarChartBase<PieData> {
for (int j = 0; j < set.getEntryCount(); j++) {
mDrawAngles[cnt] = calcAngle(Math.abs(set.getEntryForIndex(j).getY()), yValueSum);
float drawAngle = calcAngle(Math.abs(set.getEntryForIndex(j).getY()), yValueSum);
if (hasMinAngle) {
float temp = drawAngle - mMinAngleForSlices;
if (temp <= 0) {
minAngles[cnt] = mMinAngleForSlices;
offset += -temp;
} else {
minAngles[cnt] = drawAngle;
diff += temp;
}
}
mDrawAngles[cnt] = drawAngle;
if (cnt == 0) {
mAbsoluteAngles[cnt] = mDrawAngles[cnt];
@ -248,6 +272,20 @@ public class PieChart extends PieRadarChartBase<PieData> {
}
}
if (hasMinAngle) {
// Correct bigger slices by relatively reducing their angles based on the total angle needed to subtract
// This requires that `entryCount * mMinAngleForSlices <= mMaxAngle` be true to properly work!
for (int i = 0; i < entryCount; i++) {
minAngles[i] -= (minAngles[i] - mMinAngleForSlices) / diff * offset;
if (i == 0) {
mAbsoluteAngles[0] = minAngles[0];
} else {
mAbsoluteAngles[i] = mAbsoluteAngles[i - 1] + minAngles[i];
}
}
mDrawAngles = minAngles;
}
}
/**
@ -729,6 +767,32 @@ public class PieChart extends PieRadarChartBase<PieData> {
this.mMaxAngle = maxangle;
}
/**
* The minimum angle slices on the chart are rendered with, default is 0f.
*
* @return minimum angle for slices
*/
public float getMinAngleForSlices() {
return mMinAngleForSlices;
}
/**
* Set the angle to set minimum size for slices, you must call {@link #notifyDataSetChanged()}
* and {@link #invalidate()} when changing this, only works if there is enough room for all
* slices to have the minimum angle.
*
* @param minAngle minimum 0, maximum is half of {@link #setMaxAngle(float)}
*/
public void setMinAngleForSlices(float minAngle) {
if (minAngle > (mMaxAngle / 2f))
minAngle = mMaxAngle / 2f;
else if (minAngle < 0)
minAngle = 0f;
this.mMinAngleForSlices = minAngle;
}
@Override
protected void onDetachedFromWindow() {
// releases the bitmap in the renderer to avoid oom error