gpt4 book ai didi

android - MpAndroidChart 圆角饼图

转载 作者:行者123 更新时间:2023-12-05 00:16:15 51 4
gpt4 key购买 nike

我正在尝试使用 MpAndroidChart 库绘制圆角饼图。

预期输出与此类似。

enter image description here

两端都需要外圆。有一个方法 pieChart.setDrawRoundedSlices(true),但问题是饼图的起点是内圆。

这是实际的输出。

enter image description here

// initialise pie chart UI
fun initChart(mChart: PieChart) {
mChart.description.isEnabled = false
mChart.holeRadius = 75f
mChart.transparentCircleRadius = 60f
mChart.setHoleColor(Color.TRANSPARENT)
mChart.legend.isEnabled = false
mChart.isRotationEnabled = false
mChart.setTouchEnabled(false)
mChart.maxAngle = 270f
mChart.rotation = -135f
mChart.animateX(400)
mChart.setDrawRoundedSlices(true)
}

最佳答案

我最近面临同样的挑战,这是渲染器的代码,以防有人需要它:

public class RoundedSlicesPieChartRenderer extends PieChartRenderer {
public RoundedSlicesPieChartRenderer(PieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);

chart.setDrawRoundedSlices(true);
}

@Override
protected void drawDataSet(Canvas c, IPieDataSet dataSet) {
float angle = 0;
float rotationAngle = mChart.getRotationAngle();

float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();

final RectF circleBox = mChart.getCircleBox();

final int entryCount = dataSet.getEntryCount();
final float[] drawAngles = mChart.getDrawAngles();
final MPPointF center = mChart.getCenterCircleBox();
final float radius = mChart.getRadius();
final boolean drawInnerArc = mChart.isDrawHoleEnabled() && !mChart.isDrawSlicesUnderHoleEnabled();
final float userInnerRadius = drawInnerArc
? radius * (mChart.getHoleRadius() / 100.f)
: 0.f;
final float roundedRadius = (radius - (radius * mChart.getHoleRadius() / 100f)) / 2f;
final RectF roundedCircleBox = new RectF();

int visibleAngleCount = 0;
for (int j = 0; j < entryCount; j++) {
// draw only if the value is greater than zero
if ((Math.abs(dataSet.getEntryForIndex(j).getY()) > Utils.FLOAT_EPSILON)) {
visibleAngleCount++;
}
}

final float sliceSpace = visibleAngleCount <= 1 ? 0.f : getSliceSpace(dataSet);
final Path pathBuffer = new Path();
final RectF mInnerRectBuffer = new RectF();

for (int j = 0; j < entryCount; j++) {
float sliceAngle = drawAngles[j];
float innerRadius = userInnerRadius;

Entry e = dataSet.getEntryForIndex(j);

// draw only if the value is greater than zero
if (!(Math.abs(e.getY()) > Utils.FLOAT_EPSILON)) {
angle += sliceAngle * phaseX;
continue;
}

// Don't draw if it's highlighted, unless the chart uses rounded slices
if (mChart.needsHighlight(j) && !drawInnerArc) {
angle += sliceAngle * phaseX;
continue;
}

final boolean accountForSliceSpacing = sliceSpace > 0.f && sliceAngle <= 180.f;

mRenderPaint.setColor(dataSet.getColor(j));

final float sliceSpaceAngleOuter = visibleAngleCount == 1 ?
0.f :
sliceSpace / (Utils.FDEG2RAD * radius);
final float startAngleOuter = rotationAngle + (angle + sliceSpaceAngleOuter / 2.f) * phaseY;
float sweepAngleOuter = (sliceAngle - sliceSpaceAngleOuter) * phaseY;

if (sweepAngleOuter < 0.f) {
sweepAngleOuter = 0.f;
}

pathBuffer.reset();

float arcStartPointX = center.x + radius * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD);
float arcStartPointY = center.y + radius * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD);

if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) {
// Android is doing "mod 360"
pathBuffer.addCircle(center.x, center.y, radius, Path.Direction.CW);
} else {
if (drawInnerArc) {
float x = center.x + (radius - roundedRadius) * (float) Math.cos(startAngleOuter * Utils.FDEG2RAD);
float y = center.y + (radius - roundedRadius) * (float) Math.sin(startAngleOuter * Utils.FDEG2RAD);

roundedCircleBox.set(x - roundedRadius, y - roundedRadius, x + roundedRadius, y + roundedRadius);
pathBuffer.arcTo(roundedCircleBox, startAngleOuter - 180, 180);
}

pathBuffer.arcTo(
circleBox,
startAngleOuter,
sweepAngleOuter
);
}

// API < 21 does not receive floats in addArc, but a RectF
mInnerRectBuffer.set(
center.x - innerRadius,
center.y - innerRadius,
center.x + innerRadius,
center.y + innerRadius);

if (drawInnerArc && (innerRadius > 0.f || accountForSliceSpacing)) {

if (accountForSliceSpacing) {
float minSpacedRadius =
calculateMinimumRadiusForSpacedSlice(
center, radius,
sliceAngle * phaseY,
arcStartPointX, arcStartPointY,
startAngleOuter,
sweepAngleOuter);

if (minSpacedRadius < 0.f)
minSpacedRadius = -minSpacedRadius;

innerRadius = Math.max(innerRadius, minSpacedRadius);
}

final float sliceSpaceAngleInner = visibleAngleCount == 1 || innerRadius == 0.f ?
0.f :
sliceSpace / (Utils.FDEG2RAD * innerRadius);
final float startAngleInner = rotationAngle + (angle + sliceSpaceAngleInner / 2.f) * phaseY;
float sweepAngleInner = (sliceAngle - sliceSpaceAngleInner) * phaseY;
if (sweepAngleInner < 0.f) {
sweepAngleInner = 0.f;
}
final float endAngleInner = startAngleInner + sweepAngleInner;

if (sweepAngleOuter >= 360.f && sweepAngleOuter % 360f <= Utils.FLOAT_EPSILON) {
// Android is doing "mod 360"
pathBuffer.addCircle(center.x, center.y, innerRadius, Path.Direction.CCW);
} else {
float x = center.x + (radius - roundedRadius) * (float) Math.cos(endAngleInner * Utils.FDEG2RAD);
float y = center.y + (radius - roundedRadius) * (float) Math.sin(endAngleInner * Utils.FDEG2RAD);

roundedCircleBox.set(x - roundedRadius, y - roundedRadius, x + roundedRadius, y + roundedRadius);

pathBuffer.arcTo(roundedCircleBox, endAngleInner, 180);
pathBuffer.arcTo(mInnerRectBuffer, endAngleInner, -sweepAngleInner);
}
} else {

if (sweepAngleOuter % 360f > Utils.FLOAT_EPSILON) {
if (accountForSliceSpacing) {

float angleMiddle = startAngleOuter + sweepAngleOuter / 2.f;

float sliceSpaceOffset =
calculateMinimumRadiusForSpacedSlice(
center,
radius,
sliceAngle * phaseY,
arcStartPointX,
arcStartPointY,
startAngleOuter,
sweepAngleOuter);

float arcEndPointX = center.x +
sliceSpaceOffset * (float) Math.cos(angleMiddle * Utils.FDEG2RAD);
float arcEndPointY = center.y +
sliceSpaceOffset * (float) Math.sin(angleMiddle * Utils.FDEG2RAD);

pathBuffer.lineTo(
arcEndPointX,
arcEndPointY);

} else {
pathBuffer.lineTo(
center.x,
center.y);
}
}

}

pathBuffer.close();

mBitmapCanvas.drawPath(pathBuffer, mRenderPaint);

angle += sliceAngle * phaseX;
}

MPPointF.recycleInstance(center);
}
}
然后你像这样使用它:
mChart.setRenderer(new RoundedSlicesPieChartRenderer(pieChart, pieChart.getAnimator(), pieChart.getViewPortHandler()));

关于android - MpAndroidChart 圆角饼图,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61435222/

51 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com