正在查看: 爱心e站 v1.0.0 应用的 PieChartRenderer.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
正在查看: 爱心e站 v1.0.0 应用的 PieChartRenderer.java JAVA 源代码文件
本页面展示 JAVA 反编译生成的源代码文件,支持语法高亮显示。 仅供安全研究与技术分析使用,严禁用于任何非法用途。请遵守相关法律法规。
package lecho.lib.hellocharts.renderer;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PointF;
import android.graphics.PorterDuff;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.RectF;
import android.text.TextUtils;
import com.umeng.analytics.a;
import lecho.lib.hellocharts.formatter.PieChartValueFormatter;
import lecho.lib.hellocharts.model.ColumnChartData;
import lecho.lib.hellocharts.model.PieChartData;
import lecho.lib.hellocharts.model.SelectedValue;
import lecho.lib.hellocharts.model.SliceValue;
import lecho.lib.hellocharts.model.Viewport;
import lecho.lib.hellocharts.provider.PieChartDataProvider;
import lecho.lib.hellocharts.util.ChartUtils;
import lecho.lib.hellocharts.view.Chart;
public class PieChartRenderer extends AbstractChartRenderer {
private static final float DEFAULT_LABEL_INSIDE_RADIUS_FACTOR = 0.7f;
private static final float DEFAULT_LABEL_OUTSIDE_RADIUS_FACTOR = 1.0f;
private static final int DEFAULT_START_ROTATION = 45;
private static final int DEFAULT_TOUCH_ADDITIONAL_DP = 8;
private static final float MAX_WIDTH_HEIGHT = 100.0f;
private static final int MODE_DRAW = 0;
private static final int MODE_HIGHLIGHT = 1;
private Paint centerCirclePaint;
private float centerCircleScale;
private Paint.FontMetricsInt centerCircleText1FontMetrics;
private Paint centerCircleText1Paint;
private Paint.FontMetricsInt centerCircleText2FontMetrics;
private Paint centerCircleText2Paint;
private float circleFillRatio;
private PieChartDataProvider dataProvider;
private RectF drawCircleOval;
private boolean hasCenterCircle;
private boolean hasLabels;
private boolean hasLabelsOnlyForSelected;
private boolean hasLabelsOutside;
private float maxSum;
private RectF originCircleOval;
private int rotation;
private Paint separationLinesPaint;
private Paint slicePaint;
private PointF sliceVector;
private Bitmap softwareBitmap;
private Canvas softwareCanvas;
private Viewport tempMaximumViewport;
private int touchAdditional;
private PieChartValueFormatter valueFormatter;
public PieChartRenderer(Context context, Chart chart, PieChartDataProvider dataProvider) {
super(context, chart);
this.rotation = 45;
this.slicePaint = new Paint();
this.originCircleOval = new RectF();
this.drawCircleOval = new RectF();
this.sliceVector = new PointF();
this.circleFillRatio = 1.0f;
this.centerCirclePaint = new Paint();
this.centerCircleText1Paint = new Paint();
this.centerCircleText1FontMetrics = new Paint.FontMetricsInt();
this.centerCircleText2Paint = new Paint();
this.centerCircleText2FontMetrics = new Paint.FontMetricsInt();
this.separationLinesPaint = new Paint();
this.tempMaximumViewport = new Viewport();
this.softwareCanvas = new Canvas();
this.dataProvider = dataProvider;
this.touchAdditional = ChartUtils.dp2px(this.density, 8);
this.slicePaint.setAntiAlias(true);
this.slicePaint.setStyle(Paint.Style.FILL);
this.centerCirclePaint.setAntiAlias(true);
this.centerCirclePaint.setStyle(Paint.Style.FILL);
this.centerCirclePaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.SRC));
this.centerCircleText1Paint.setAntiAlias(true);
this.centerCircleText1Paint.setTextAlign(Paint.Align.CENTER);
this.centerCircleText2Paint.setAntiAlias(true);
this.centerCircleText2Paint.setTextAlign(Paint.Align.CENTER);
this.separationLinesPaint.setAntiAlias(true);
this.separationLinesPaint.setStyle(Paint.Style.STROKE);
this.separationLinesPaint.setStrokeCap(Paint.Cap.ROUND);
this.separationLinesPaint.setXfermode(new PorterDuffXfermode(PorterDuff.Mode.CLEAR));
this.separationLinesPaint.setColor(0);
}
@Override
public void onChartSizeChanged() {
calculateCircleOval();
if (this.computator.getChartWidth() > 0 && this.computator.getChartHeight() > 0) {
this.softwareBitmap = Bitmap.createBitmap(this.computator.getChartWidth(), this.computator.getChartHeight(), Bitmap.Config.ARGB_8888);
this.softwareCanvas.setBitmap(this.softwareBitmap);
}
}
@Override
public void onChartDataChanged() {
super.onChartDataChanged();
PieChartData data = this.dataProvider.getPieChartData();
this.hasLabelsOutside = data.hasLabelsOutside();
this.hasLabels = data.hasLabels();
this.hasLabelsOnlyForSelected = data.hasLabelsOnlyForSelected();
this.valueFormatter = data.getFormatter();
this.hasCenterCircle = data.hasCenterCircle();
this.centerCircleScale = data.getCenterCircleScale();
this.centerCirclePaint.setColor(data.getCenterCircleColor());
if (data.getCenterText1Typeface() != null) {
this.centerCircleText1Paint.setTypeface(data.getCenterText1Typeface());
}
this.centerCircleText1Paint.setTextSize(ChartUtils.sp2px(this.scaledDensity, data.getCenterText1FontSize()));
this.centerCircleText1Paint.setColor(data.getCenterText1Color());
this.centerCircleText1Paint.getFontMetricsInt(this.centerCircleText1FontMetrics);
if (data.getCenterText2Typeface() != null) {
this.centerCircleText2Paint.setTypeface(data.getCenterText2Typeface());
}
this.centerCircleText2Paint.setTextSize(ChartUtils.sp2px(this.scaledDensity, data.getCenterText2FontSize()));
this.centerCircleText2Paint.setColor(data.getCenterText2Color());
this.centerCircleText2Paint.getFontMetricsInt(this.centerCircleText2FontMetrics);
onChartViewportChanged();
}
@Override
public void onChartViewportChanged() {
if (this.isViewportCalculationEnabled) {
calculateMaxViewport();
this.computator.setMaxViewport(this.tempMaximumViewport);
this.computator.setCurrentViewport(this.computator.getMaximumViewport());
}
}
@Override
public void draw(Canvas canvas) {
Canvas drawCanvas;
if (this.softwareBitmap != null) {
drawCanvas = this.softwareCanvas;
drawCanvas.drawColor(0, PorterDuff.Mode.CLEAR);
} else {
drawCanvas = canvas;
}
drawSlices(drawCanvas);
drawSeparationLines(drawCanvas);
if (this.hasCenterCircle) {
drawCenterCircle(drawCanvas);
}
drawLabels(drawCanvas);
if (this.softwareBitmap != null) {
canvas.drawBitmap(this.softwareBitmap, ColumnChartData.DEFAULT_BASE_VALUE, ColumnChartData.DEFAULT_BASE_VALUE, (Paint) null);
}
}
@Override
public void drawUnclipped(Canvas canvas) {
}
@Override
public boolean checkTouch(float touchX, float touchY) {
this.selectedValue.clear();
PieChartData data = this.dataProvider.getPieChartData();
float centerX = this.originCircleOval.centerX();
float centerY = this.originCircleOval.centerY();
float circleRadius = this.originCircleOval.width() / 2.0f;
this.sliceVector.set(touchX - centerX, touchY - centerY);
if (this.sliceVector.length() > this.touchAdditional + circleRadius) {
return false;
}
if (data.hasCenterCircle() && this.sliceVector.length() < data.getCenterCircleScale() * circleRadius) {
return false;
}
float touchAngle = ((pointToAngle(touchX, touchY, centerX, centerY) - this.rotation) + 360.0f) % 360.0f;
float sliceScale = 360.0f / this.maxSum;
float lastAngle = ColumnChartData.DEFAULT_BASE_VALUE;
int sliceIndex = 0;
for (SliceValue sliceValue : data.getValues()) {
float angle = Math.abs(sliceValue.getValue()) * sliceScale;
if (touchAngle >= lastAngle) {
this.selectedValue.set(sliceIndex, sliceIndex, SelectedValue.SelectedValueType.NONE);
}
lastAngle += angle;
sliceIndex++;
}
return isTouched();
}
private void drawCenterCircle(Canvas canvas) {
PieChartData data = this.dataProvider.getPieChartData();
float circleRadius = this.originCircleOval.width() / 2.0f;
float centerRadius = circleRadius * data.getCenterCircleScale();
float centerX = this.originCircleOval.centerX();
float centerY = this.originCircleOval.centerY();
canvas.drawCircle(centerX, centerY, centerRadius, this.centerCirclePaint);
if (!TextUtils.isEmpty(data.getCenterText1())) {
int text1Height = Math.abs(this.centerCircleText1FontMetrics.ascent);
if (!TextUtils.isEmpty(data.getCenterText2())) {
int text2Height = Math.abs(this.centerCircleText2FontMetrics.ascent);
canvas.drawText(data.getCenterText1(), centerX, centerY - (text1Height * 0.2f), this.centerCircleText1Paint);
canvas.drawText(data.getCenterText2(), centerX, text2Height + centerY, this.centerCircleText2Paint);
return;
}
canvas.drawText(data.getCenterText1(), centerX, (text1Height / 4) + centerY, this.centerCircleText1Paint);
}
}
private void drawSlices(Canvas canvas) {
PieChartData data = this.dataProvider.getPieChartData();
float sliceScale = 360.0f / this.maxSum;
float lastAngle = this.rotation;
int sliceIndex = 0;
for (SliceValue sliceValue : data.getValues()) {
float angle = Math.abs(sliceValue.getValue()) * sliceScale;
if (isTouched() && this.selectedValue.getFirstIndex() == sliceIndex) {
drawSlice(canvas, sliceValue, lastAngle, angle, 1);
} else {
drawSlice(canvas, sliceValue, lastAngle, angle, 0);
}
lastAngle += angle;
sliceIndex++;
}
}
private void drawSeparationLines(Canvas canvas) {
int sliceSpacing;
PieChartData data = this.dataProvider.getPieChartData();
if (data.getValues().size() >= 2 && (sliceSpacing = ChartUtils.dp2px(this.density, data.getSlicesSpacing())) >= 1) {
float sliceScale = 360.0f / this.maxSum;
float lastAngle = this.rotation;
float circleRadius = this.originCircleOval.width() / 2.0f;
this.separationLinesPaint.setStrokeWidth(sliceSpacing);
for (SliceValue sliceValue : data.getValues()) {
float angle = Math.abs(sliceValue.getValue()) * sliceScale;
this.sliceVector.set((float) Math.cos(Math.toRadians(lastAngle)), (float) Math.sin(Math.toRadians(lastAngle)));
normalizeVector(this.sliceVector);
float x1 = (this.sliceVector.x * (this.touchAdditional + circleRadius)) + this.originCircleOval.centerX();
float y1 = (this.sliceVector.y * (this.touchAdditional + circleRadius)) + this.originCircleOval.centerY();
canvas.drawLine(this.originCircleOval.centerX(), this.originCircleOval.centerY(), x1, y1, this.separationLinesPaint);
lastAngle += angle;
}
}
}
public void drawLabels(Canvas canvas) {
PieChartData data = this.dataProvider.getPieChartData();
float sliceScale = 360.0f / this.maxSum;
float lastAngle = this.rotation;
int sliceIndex = 0;
for (SliceValue sliceValue : data.getValues()) {
float angle = Math.abs(sliceValue.getValue()) * sliceScale;
if (isTouched()) {
if (this.hasLabels) {
drawLabel(canvas, sliceValue, lastAngle, angle);
} else if (this.hasLabelsOnlyForSelected && this.selectedValue.getFirstIndex() == sliceIndex) {
drawLabel(canvas, sliceValue, lastAngle, angle);
}
} else if (this.hasLabels) {
drawLabel(canvas, sliceValue, lastAngle, angle);
}
lastAngle += angle;
sliceIndex++;
}
}
private void drawSlice(Canvas canvas, SliceValue sliceValue, float lastAngle, float angle, int mode) {
this.sliceVector.set((float) Math.cos(Math.toRadians((angle / 2.0f) + lastAngle)), (float) Math.sin(Math.toRadians((angle / 2.0f) + lastAngle)));
normalizeVector(this.sliceVector);
this.drawCircleOval.set(this.originCircleOval);
if (1 == mode) {
this.drawCircleOval.inset(-this.touchAdditional, -this.touchAdditional);
this.slicePaint.setColor(sliceValue.getDarkenColor());
canvas.drawArc(this.drawCircleOval, lastAngle, angle, true, this.slicePaint);
} else {
this.slicePaint.setColor(sliceValue.getColor());
canvas.drawArc(this.drawCircleOval, lastAngle, angle, true, this.slicePaint);
}
}
private void drawLabel(Canvas canvas, SliceValue sliceValue, float lastAngle, float angle) {
float labelRadius;
float left;
float right;
float top;
float bottom;
this.sliceVector.set((float) Math.cos(Math.toRadians((angle / 2.0f) + lastAngle)), (float) Math.sin(Math.toRadians((angle / 2.0f) + lastAngle)));
normalizeVector(this.sliceVector);
int numChars = this.valueFormatter.formatChartValue(this.labelBuffer, sliceValue);
if (numChars != 0) {
float labelWidth = this.labelPaint.measureText(this.labelBuffer, this.labelBuffer.length - numChars, numChars);
int labelHeight = Math.abs(this.fontMetrics.ascent);
float centerX = this.originCircleOval.centerX();
float centerY = this.originCircleOval.centerY();
float circleRadius = this.originCircleOval.width() / 2.0f;
if (this.hasLabelsOutside) {
labelRadius = circleRadius * 1.0f;
} else if (this.hasCenterCircle) {
labelRadius = circleRadius - ((circleRadius - (this.centerCircleScale * circleRadius)) / 2.0f);
} else {
labelRadius = circleRadius * DEFAULT_LABEL_INSIDE_RADIUS_FACTOR;
}
float rawX = (this.sliceVector.x * labelRadius) + centerX;
float rawY = (this.sliceVector.y * labelRadius) + centerY;
if (this.hasLabelsOutside) {
if (rawX > centerX) {
left = rawX + this.labelMargin;
right = rawX + labelWidth + (this.labelMargin * 3);
} else {
left = (rawX - labelWidth) - (this.labelMargin * 3);
right = rawX - this.labelMargin;
}
if (rawY > centerY) {
top = rawY + this.labelMargin;
bottom = labelHeight + rawY + (this.labelMargin * 3);
} else {
top = (rawY - labelHeight) - (this.labelMargin * 3);
bottom = rawY - this.labelMargin;
}
} else {
left = (rawX - (labelWidth / 2.0f)) - this.labelMargin;
right = (labelWidth / 2.0f) + rawX + this.labelMargin;
top = (rawY - (labelHeight / 2)) - this.labelMargin;
bottom = (labelHeight / 2) + rawY + this.labelMargin;
}
this.labelBackgroundRect.set(left, top, right, bottom);
drawLabelTextAndBackground(canvas, this.labelBuffer, this.labelBuffer.length - numChars, numChars, sliceValue.getDarkenColor());
}
}
private void normalizeVector(PointF point) {
float abs = point.length();
point.set(point.x / abs, point.y / abs);
}
private float pointToAngle(float x, float y, float centerX, float centerY) {
double diffX = x - centerX;
double diffY = y - centerY;
double radian = Math.atan2(-diffX, diffY);
float angle = (((float) Math.toDegrees(radian)) + 360.0f) % 360.0f;
return angle + 90.0f;
}
private void calculateCircleOval() {
Rect contentRect = this.computator.getContentRectMinusAllMargins();
float circleRadius = Math.min(contentRect.width() / 2.0f, contentRect.height() / 2.0f);
float centerX = contentRect.centerX();
float centerY = contentRect.centerY();
float left = (centerX - circleRadius) + this.touchAdditional;
float top = (centerY - circleRadius) + this.touchAdditional;
float right = (centerX + circleRadius) - this.touchAdditional;
float bottom = (centerY + circleRadius) - this.touchAdditional;
this.originCircleOval.set(left, top, right, bottom);
float inest = 0.5f * this.originCircleOval.width() * (1.0f - this.circleFillRatio);
this.originCircleOval.inset(inest, inest);
}
private void calculateMaxViewport() {
this.tempMaximumViewport.set(ColumnChartData.DEFAULT_BASE_VALUE, MAX_WIDTH_HEIGHT, MAX_WIDTH_HEIGHT, ColumnChartData.DEFAULT_BASE_VALUE);
this.maxSum = ColumnChartData.DEFAULT_BASE_VALUE;
for (SliceValue sliceValue : this.dataProvider.getPieChartData().getValues()) {
this.maxSum += Math.abs(sliceValue.getValue());
}
}
public RectF getCircleOval() {
return this.originCircleOval;
}
public void setCircleOval(RectF orginCircleOval) {
this.originCircleOval = orginCircleOval;
}
public int getChartRotation() {
return this.rotation;
}
public void setChartRotation(int rotation) {
this.rotation = ((rotation % a.p) + a.p) % a.p;
}
public SliceValue getValueForAngle(int angle, SelectedValue selectedValue) {
PieChartData data = this.dataProvider.getPieChartData();
float touchAngle = ((angle - this.rotation) + 360.0f) % 360.0f;
float sliceScale = 360.0f / this.maxSum;
float lastAngle = ColumnChartData.DEFAULT_BASE_VALUE;
int sliceIndex = 0;
for (SliceValue sliceValue : data.getValues()) {
float tempAngle = Math.abs(sliceValue.getValue()) * sliceScale;
if (touchAngle >= lastAngle) {
if (selectedValue != null) {
selectedValue.set(sliceIndex, sliceIndex, SelectedValue.SelectedValueType.NONE);
return sliceValue;
}
return sliceValue;
}
lastAngle += tempAngle;
sliceIndex++;
}
return null;
}
public float getCircleFillRatio() {
return this.circleFillRatio;
}
public void setCircleFillRatio(float fillRatio) {
if (fillRatio < ColumnChartData.DEFAULT_BASE_VALUE) {
fillRatio = ColumnChartData.DEFAULT_BASE_VALUE;
} else if (fillRatio > 1.0f) {
fillRatio = 1.0f;
}
this.circleFillRatio = fillRatio;
calculateCircleOval();
}
}