Skip to content

Commit

Permalink
Support for word wrapping center text in pie chart (default: false)
Browse files Browse the repository at this point in the history
  • Loading branch information
danielgindi committed May 21, 2015
1 parent 1afbe59 commit b4469dc
Show file tree
Hide file tree
Showing 2 changed files with 114 additions and 23 deletions.
38 changes: 38 additions & 0 deletions MPChartLib/src/com/github/mikephil/charting/charts/PieChart.java
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,10 @@ public class PieChart extends PieRadarChartBase<PieData> {
/** if enabled, centertext is drawn */
private boolean mDrawCenterText = true;

private boolean mCenterTextWordWrapEnabled = false;

private float mCenterTextRadiusPercent = 1.f;

public PieChart(Context context) {
super(context);
}
Expand Down Expand Up @@ -519,4 +523,38 @@ public void setUsePercentValues(boolean enabled) {
public boolean isUsePercentValuesEnabled() {
return mUsePercentValues;
}

/**
* should the center text be word wrapped?
* note that word wrapping takes a toll on performance
* if word wrapping is disabled, newlines are still respected
*/
public void setCenterTextWordWrapEnabled(boolean enabled) {
mCenterTextWordWrapEnabled = enabled;
}

/**
* should the center text be word wrapped?
* note that word wrapping takes a toll on performance
* if word wrapping is disabled, newlines are still respected
*/
public boolean isCenterTextWordWrapEnabled() {
return mCenterTextWordWrapEnabled;
}

/**
* the rectangular radius of the bounding box for the center text, as a percentage of the pie hole
* default 1.f (100%)
*/
public void setCenterTextRadiusPercent(float percent) {
mCenterTextRadiusPercent = percent;
}

/**
* the rectangular radius of the bounding box for the center text, as a percentage of the pie hole
* default 1.f (100%)
*/
public float getCenterTextRadiusPercent() {
return mCenterTextRadiusPercent;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
import android.graphics.Paint.Style;
import android.graphics.PointF;
import android.graphics.RectF;
import android.text.Layout;
import android.text.StaticLayout;
import android.text.TextPaint;

import com.github.mikephil.charting.animation.ChartAnimator;
import com.github.mikephil.charting.charts.PieChart;
Expand Down Expand Up @@ -36,7 +39,12 @@ public class PieChartRenderer extends DataRenderer {
* paint object for the text that can be displayed in the center of the
* chart
*/
private Paint mCenterTextPaint;
private TextPaint mCenterTextPaint;

private StaticLayout mCenterTextLayout;
private String mCenterTextLastValue;
private RectF mCenterTextLastBounds = new RectF();
private RectF[] mRectBuffer = { new RectF(), new RectF(), new RectF() };

/** Bitmap for drawing the center hole */
protected Bitmap mDrawBitmap;
Expand All @@ -56,7 +64,7 @@ public PieChartRenderer(PieChart chart, ChartAnimator animator,
mTransparentCirclePaint.setColor(Color.WHITE);
mTransparentCirclePaint.setStyle(Style.FILL);

mCenterTextPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mCenterTextPaint = new TextPaint(Paint.ANTI_ALIAS_FLAG);
mCenterTextPaint.setColor(Color.BLACK);
mCenterTextPaint.setTextSize(Utils.convertDpToPixel(12f));
mCenterTextPaint.setTextAlign(Align.CENTER);
Expand All @@ -74,7 +82,7 @@ public Paint getPaintTransparentCircle() {
return mTransparentCirclePaint;
}

public Paint getPaintCenterText() {
public TextPaint getPaintCenterText() {
return mCenterTextPaint;
}

Expand Down Expand Up @@ -282,35 +290,80 @@ protected void drawCenterText(Canvas c) {

PointF center = mChart.getCenterCircleBox();

// get all lines from the text
String[] lines = centerText.split("\n");
if (mChart.isCenterTextWordWrapEnabled()) {

float maxlineheight = 0f;
float innerRadius = mChart.isDrawHoleEnabled() && mChart.isHoleTransparent() ? mChart.getRadius() * (mChart.getHoleRadius() / 100f) : mChart.getRadius();

// calc the maximum line height
for (String line : lines) {
float curHeight = Utils.calcTextHeight(mCenterTextPaint, line);
if (curHeight > maxlineheight)
maxlineheight = curHeight;
}
RectF holeRect = mRectBuffer[0];
holeRect.left = center.x - innerRadius;
holeRect.top = center.y - innerRadius;
holeRect.right = center.x + innerRadius;
holeRect.bottom = center.y + innerRadius;
RectF boundingRect = mRectBuffer[1];
boundingRect.set(holeRect);

float linespacing = maxlineheight * 0.25f;
float radiusPercent = mChart.getCenterTextRadiusPercent();
if (radiusPercent > 0.0) {
boundingRect.inset((boundingRect.width() - boundingRect.width() * radiusPercent) / 2.f,
(boundingRect.height() - boundingRect.height() * radiusPercent) / 2.f);
}

float totalheight = maxlineheight * lines.length - linespacing * (lines.length - 1);
if (!centerText.equals(mCenterTextLastValue) || !boundingRect.equals(mCenterTextLastBounds)) {

int cnt = lines.length;
// Next time we won't recalculate StaticLayout...
mCenterTextLastBounds.set(boundingRect);
mCenterTextLastValue = centerText;

// If width is 0, it will crash. Always have a minimum of 1
mCenterTextLayout = new StaticLayout(centerText, 0, centerText.length(),
mCenterTextPaint,
(int)Math.max(Math.ceil(mCenterTextLastBounds.width()), 1.f),
Layout.Alignment.ALIGN_NORMAL, 1.f, 0.f, false);
}

float y = center.y;
// I wish we could make an ellipse clipping path on Android to clip to the hole...
// If we ever find out how, this is the place to add it, based on holeRect

for (int i = 0; i < lines.length; i++) {
float layoutWidth = Utils.getStaticLayoutMaxWidth(mCenterTextLayout),
layoutHeight = mCenterTextLayout.getHeight();

String line = lines[lines.length - i - 1];
c.save();
c.translate(boundingRect.centerX(), boundingRect.top + (boundingRect.height() - layoutHeight) / 2.f);
mCenterTextLayout.draw(c);
c.restore();

c.drawText(line, center.x, y
+ maxlineheight * cnt - totalheight / 2f,
mCenterTextPaint);
cnt--;
y -= linespacing;
} else {

// get all lines from the text
String[] lines = centerText.split("\n");

float maxlineheight = 0f;

// calc the maximum line height
for (String line : lines) {
float curHeight = Utils.calcTextHeight(mCenterTextPaint, line);
if (curHeight > maxlineheight)
maxlineheight = curHeight;
}

float linespacing = maxlineheight * 0.25f;

float totalheight = maxlineheight * lines.length - linespacing * (lines.length - 1);

int cnt = lines.length;

float y = center.y;

for (int i = 0; i < lines.length; i++) {

String line = lines[lines.length - i - 1];

c.drawText(line, center.x, y
+ maxlineheight * cnt - totalheight / 2f,
mCenterTextPaint);
cnt--;
y -= linespacing;
}
}
}
}
Expand Down

0 comments on commit b4469dc

Please sign in to comment.