Я использую mpandroid charting library. Я изменил PieChartRenderer и смог получить такой график.Нажмите события на круговой диаграмме - mpandroid
PieChartRenderer
public class ImagePieChartRenderer extends PieChartRenderer {
private ArrayList<Bitmap> bitMaps;
private Paint mEntryLabelsPaint;
public ImagePieChartRenderer(PieChart chart, ChartAnimator animator, ViewPortHandler viewPortHandler, ArrayList<Bitmap> bitMaps) {
super(chart, animator, viewPortHandler);
this.bitMaps = bitMaps;
mEntryLabelsPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mEntryLabelsPaint.setColor(Color.BLACK);
mEntryLabelsPaint.setTextAlign(Paint.Align.CENTER);
mEntryLabelsPaint.setTextSize(Utils.convertDpToPixel(13f));
}
@Override
protected void drawDataSet(Canvas c, IPieDataSet dataSet) {
drawImages(c);
super.drawDataSet(c, dataSet);
}
private void drawImages(Canvas c) {
MPPointF center = mChart.getCenterCircleBox();
// get whole the radius
float radius = mChart.getRadius();
float rotationAngle = mChart.getRotationAngle();
float[] drawAngles = mChart.getDrawAngles();
float[] absoluteAngles = mChart.getAbsoluteAngles();
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
final float holeRadiusPercent = mChart.getHoleRadius()/100.f;
float labelRadiusOffset = radius/10f * 3.6f;
labelRadiusOffset = (radius - (radius * holeRadiusPercent))/2f;
final float labelRadius = radius - labelRadiusOffset;
PieData data = mChart.getData();
List<IPieDataSet> dataSets = data.getDataSets();
float yValueSum = data.getYValueSum();
float angle;
int xIndex = 0;
c.save();
float offset = Utils.convertDpToPixel(5.f);
for (int i = 0; i < dataSets.size(); i++) {
IPieDataSet dataSet = dataSets.get(i);
// apply the text-styling defined by the DataSet
applyValueTextStyle(dataSet);
float lineHeight = Utils.calcTextHeight(mValuePaint, "Q")
+ Utils.convertDpToPixel(4f);
IValueFormatter formatter = dataSet.getValueFormatter();
int entryCount = dataSet.getEntryCount();
mValueLinePaint.setColor(dataSet.getValueLineColor());
mValueLinePaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getValueLineWidth()));
final float sliceSpace = getSliceSpace(dataSet);
for (int j = 0; j < entryCount; j++) {
PieEntry entry = dataSet.getEntryForIndex(j);
if (xIndex == 0)
angle = 0.f;
else
angle = absoluteAngles[xIndex - 1] * phaseX;
final float sliceAngle = drawAngles[xIndex];
final float sliceSpaceMiddleAngle = sliceSpace/(Utils.FDEG2RAD * labelRadius);
// offset needed to center the drawn text in the slice
final float angleOffset = (sliceAngle - sliceSpaceMiddleAngle/2.f)/2.f;
angle = angle + angleOffset;
final float transformedAngle = rotationAngle + angle * phaseY;
float value = mChart.isUsePercentValuesEnabled() ? entry.getY()
/yValueSum * 100f : entry.getY();
final float sliceXBase = (float) Math.cos(transformedAngle * Utils.FDEG2RAD);
final float sliceYBase = (float) Math.sin(transformedAngle * Utils.FDEG2RAD);
final float valueLineLength1 = dataSet.getValueLinePart1Length();
final float valueLineLength2 = dataSet.getValueLinePart2Length();
final float valueLinePart1OffsetPercentage = dataSet.getValueLinePart1OffsetPercentage()/100.f;
float pt2x, pt2y;
float labelPtx, labelPty;
float percentX, percentY;
float line1Radius;
line1Radius = (radius - (radius * holeRadiusPercent))
* valueLinePart1OffsetPercentage
+ (radius * holeRadiusPercent);
final float polyline2Width = dataSet.isValueLineVariableLength()
? labelRadius * valueLineLength2 * (float) Math.abs(Math.sin(
transformedAngle * Utils.FDEG2RAD))
: labelRadius * valueLineLength2;
final float pt0x = line1Radius * sliceXBase + center.x;
final float pt0y = line1Radius * sliceYBase + center.y;
final float pt1x = labelRadius * (1 + valueLineLength1) * sliceXBase + center.x;
final float pt1y = labelRadius * (1 + valueLineLength1) * sliceYBase + center.y;
if (transformedAngle % 360.0 >= 40.0 && transformedAngle % 360.0 <= 130.0) {
pt2x = pt1x + polyline2Width;
pt2y = pt1y;
Log.d(entry.getLabel(), "TWO "+ transformedAngle % 360.0);
mValuePaint.setTextAlign(Paint.Align.LEFT);
mEntryLabelsPaint.setTextAlign(Paint.Align.LEFT);
labelPtx = pt2x;
labelPty = pt2y;
percentX = labelPtx - 1.5f*offset ;
percentY = labelPty + bitMaps.get(j).getHeight() + 2.2f*offset;
} else {
pt2x = pt1x - polyline2Width;
pt2y = pt1y;
Log.d(entry.getLabel(), "ONE "+ transformedAngle % 360.0);
mValuePaint.setTextAlign(Paint.Align.RIGHT);
mEntryLabelsPaint.setTextAlign(Paint.Align.RIGHT);
labelPtx = pt2x;
labelPty = pt2y;
percentX = labelPtx + 1.5f*offset;
percentY = labelPty - bitMaps.get(j).getHeight() - 0.5f*offset;
}
mValueLinePaint.setColor(dataSet.getColor(j));
c.drawLine(pt0x, pt0y, pt1x, pt1y, mValueLinePaint);
c.drawLine(pt1x, pt1y, pt2x, pt2y, mValueLinePaint);
// draw everything, depending on settings
drawValue(c,
formatter,
value,
entry,
0,
percentX,
percentY,
dataSet.getValueTextColor(j));
Paint paint = new Paint();
paint.setStyle(Paint.Style.FILL);
paint.setColor(dataSet.getColor(j));
c.drawCircle(labelPtx, labelPty, bitMaps.get(j).getWidth(), paint);
c.drawBitmap(bitMaps.get(j), labelPtx-bitMaps.get(j).getWidth()/2f, labelPty-bitMaps.get(j).getHeight()/2, null);
// if (j < data.getEntryCount() && entry.getLabel() != null) {
// drawEntryLabel(c, entry.getLabel(), labelPtx, labelPty + lineHeight);
// }
xIndex++;
}
}
MPPointF.recycleInstance(center);
c.restore();
}
}
Теперь мне нужно, чтобы иметь возможность нажмите на маленькие круги вокруг диаграммы. Может кто-то, пожалуйста, укажите мне классы и функции, которые необходимо изменить для достижения этого.
В основном я хочу вызвать onValueSelected(Entry e, Highlight h)
, когда касаюсь кругов.
Спасибо. Я дам вам шанс и дам вам знать. – amarok
Я обновил свой ответ - то, что вы просите, немного сложнее, чем я думал. Я думаю, вам придется кэшировать значения x и y для среза, когда вы кешируете метки x и y, чтобы вы могли сопоставить их. –
Просто хотелось убедиться, что LabelPointCache является настраиваемым объектом и не принадлежит самой библиотеке. Кроме того, не будет ли эта логика искать одну точку вместо того, чтобы искать всю область круга. – amarok