我正在尝试使用MPAndroidChart为我的Android应用程序创建下面这样的图表。但我无法弄清楚如何将条形图的边缘变为圆角。它总是呈现为方形边缘。
您能否建议我该怎么做?
提前感谢您的帮助。
我正在尝试使用MPAndroidChart为我的Android应用程序创建下面这样的图表。但我无法弄清楚如何将条形图的边缘变为圆角。它总是呈现为方形边缘。
您能否建议我该怎么做?
提前感谢您的帮助。
我尝试结合 @mallaudin 和 @Janusz Hain 的代码。现在它可以工作了,谢谢!!!以下是我的代码。
public class CustomBarChartRender extends BarChartRenderer {
private RectF mBarShadowRectBuffer = new RectF();
private int mRadius;
public CustomBarChartRender(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
public void setRadius(int mRadius) {
this.mRadius = mRadius;
}
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mBarBorderPaint.setColor(dataSet.getBarBorderColor());
mBarBorderPaint.setStrokeWidth(Utils.convertDpToPixel(dataSet.getBarBorderWidth()));
mShadowPaint.setColor(dataSet.getBarShadowColor());
boolean drawBorder = dataSet.getBarBorderWidth() > 0f;
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
if (mChart.isDrawBarShadowEnabled()) {
mShadowPaint.setColor(dataSet.getBarShadowColor());
BarData barData = mChart.getBarData();
float barWidth = barData.getBarWidth();
float barWidthHalf = barWidth / 2.0f;
float x;
int i = 0;
double count = Math.min(Math.ceil((int) (double) ((float) dataSet.getEntryCount() * phaseX)), dataSet.getEntryCount());
while (i < count) {
BarEntry e = dataSet.getEntryForIndex(i);
x = e.getX();
mBarShadowRectBuffer.left = x - barWidthHalf;
mBarShadowRectBuffer.right = x + barWidthHalf;
trans.rectValueToPixel(mBarShadowRectBuffer);
if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) {
i++;
continue;
}
if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
break;
mBarShadowRectBuffer.top = mViewPortHandler.contentTop();
mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom();
c.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint);
i++;
}
}
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setDataSet(index);
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.setBarWidth(mChart.getBarData().getBarWidth());
buffer.feed(dataSet);
trans.pointValuesToPixel(buffer.buffer);
boolean isSingleColor = dataSet.getColors().size() == 1;
if (isSingleColor) {
mRenderPaint.setColor(dataSet.getColor());
}
int j = 0;
while (j < buffer.size()) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) {
j += 4;
continue;
}
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (!isSingleColor) {
// Set the color for the currently drawn value. If the index
// is out of bounds, reuse colors.
mRenderPaint.setColor(dataSet.getColor(j / 4));
}
if (dataSet.getGradientColor() != null) {
GradientColor gradientColor = dataSet.getGradientColor();
mRenderPaint.setShader(new LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
gradientColor.getStartColor(),
gradientColor.getEndColor(),
android.graphics.Shader.TileMode.MIRROR));
}
if (dataSet.getGradientColors() != null) {
mRenderPaint.setShader(new LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
dataSet.getGradientColor(j / 4).getStartColor(),
dataSet.getGradientColor(j / 4).getEndColor(),
Shader.TileMode.MIRROR));
}
Path path2 = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
c.drawPath(path2, mRenderPaint);
if (drawBorder) {
Path path = roundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, true, true, false, false);
c.drawPath(path, mBarBorderPaint);
}
j += 4;
}
}
private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
float top = rect.top;
float left = rect.left;
float right = rect.right;
float bottom = rect.bottom;
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else {
path.rLineTo(0, -ry);
path.rLineTo(-rx, 0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else {
path.rLineTo(-rx, 0);
path.rLineTo(0, ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else {
path.rLineTo(0, ry);
path.rLineTo(rx, 0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else {
path.rLineTo(rx, 0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}}
在其他类中:
CustomBarChartRender barChartRender = new CustomBarChartRender(barChart,barChart.getAnimator(), barChart.getViewPortHandler());
barChartRender.setRadius(20);
barChart.setRenderer(barChartRender);
我已经在库本身上实现了解决方案。
首先,创建一个attrs.xml文件,添加一个新属性以在图表视图中使用。类似以下内容:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<declare-styleable name="BarChart">
<attr name="radius" format="integer" />
</declare-styleable>
</resources>
然后编辑BarChartRenderer上名为drawDataSet的方法:
protected void drawDataSet(Canvas c, BarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mShadowPaint.setColor(dataSet.getBarShadowColor());
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
List<BarEntry> entries = dataSet.getYVals();
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setBarSpace(dataSet.getBarSpace());
buffer.setDataSet(index);
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.feed(entries);
trans.pointValuesToPixel(buffer.buffer);
// if multiple colors
if (dataSet.getColors().size() > 1) {
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom(), mShadowPaint);
}
// Set the color for the currently drawn value. If the index
// is
// out of bounds, reuse colors.
mRenderPaint.setColor(dataSet.getColor(j / 4));
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
} else {
mRenderPaint.setColor(dataSet.getColor());
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
}
}
这样做可以改变矩形本身,但不会影响其高亮部分。因此,请修改drawHighlighted方法中的以下代码:
if (mRadius > 0)
c.drawRoundRect(mBarRect, mRadius, mRadius, mHighlightPaint);
else
c.drawRect(mBarRect, mHighlightPaint);
public void setRadius (int radius) {
mRadius = radius;
}
最后,在BarChart对象上创建一个新的构造函数来获取半径属性:
public BarChart(Context context, AttributeSet attrs) {
super(context, attrs);
mRadius = attrs.getAttributeIntValue("http://schemas.android.com/apk/res-auto", "radius", 0);
((BarChartRenderer)mRenderer).setRadius(mRadius);
}
大功告成!愉快地编程吧 :)
从MPAndroidChart的最后一段代码创建完整的要点:
https://gist.github.com/xanscale/e971cc4f2f0712a8a3bcc35e85325c27
1) 添加以下类:
public class RoundedBarChart extends BarChartRenderer {
public RoundedBarChart(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
}
private float mRadius=5f;
public void setmRadius(float mRadius) {
this.mRadius = mRadius;
}
@Override
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mShadowPaint.setColor(dataSet.getBarShadowColor());
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
if(mBarBuffers!=null){
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setDataSet(index);
buffer.setBarWidth(mChart.getBarData().getBarWidth());
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.feed(dataSet);
trans.pointValuesToPixel(buffer.buffer);
// if multiple colors
if (dataSet.getColors().size() > 1) {
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(), buffer.buffer[j + 2], mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(), buffer.buffer[j + 2], mViewPortHandler.contentBottom(), mShadowPaint);
}
// Set the color for the currently drawn value. If the index
// is
// out of bounds, reuse colors.
mRenderPaint.setColor(dataSet.getColor(j / 4));
if (mRadius > 0){
Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
c.drawPath(path,mRenderPaint);
}
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2], buffer.buffer[j + 3], mRenderPaint);
}
} else {
mRenderPaint.setColor(dataSet.getColor());
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
if (mRadius > 0){
Path path = RoundedRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2] , buffer.buffer[j + 3] , 15,15, true, true, false, false);
c.drawPath(path,mRenderPaint);
}
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
}
}
}
public static Path RoundedRect(
float left, float top, float right, float bottom, float rx, float ry,
boolean tl, boolean tr, boolean br, boolean bl
){
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else{
path.rLineTo(0, -ry);
path.rLineTo(-rx,0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else{
path.rLineTo(-rx, 0);
path.rLineTo(0,ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else{
path.rLineTo(0, ry);
path.rLineTo(rx,0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else{
path.rLineTo(rx,0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
}
2) 使用 barChart.renderer = RoundedBarChart(barChart, barChart.animator, barChart.viewPortHandler)
BarChartCustomRenderer customRenderer = BarChartCustomRenderer(mDashBoardBinding.topperChart, mDashBoardBinding.topperChart.getAnimator(), mDashBoardBinding.topperChart.getViewPortHandler());
topperChart.setRenderer(customRenderer);
drawDataSet: 绘制数据集。
protected void drawDataSet(Canvas c, IBarDataSet dataSet, int index) {
Transformer trans = mChart.getTransformer(dataSet.getAxisDependency());
mShadowPaint.setColor(dataSet.getBarShadowColor());
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
// initialize the buffer
BarBuffer buffer = mBarBuffers[index];
buffer.setPhases(phaseX, phaseY);
buffer.setDataSet(index);
buffer.setBarWidth(mChart.getBarData().getBarWidth());
buffer.setInverted(mChart.isInverted(dataSet.getAxisDependency()));
buffer.feed(dataSet);
trans.pointValuesToPixel(buffer.buffer);
// if multiple colors
if (dataSet.getColors().size() > 1) {
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom(), mShadowPaint);
}
// Set the color for the currently drawn value. If the index
// is
// out of bounds, reuse colors.
mRenderPaint.setColor(dataSet.getColor(j / 4));
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
} else {
mRenderPaint.setColor(dataSet.getColor());
for (int j = 0; j < buffer.size(); j += 4) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
continue;
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break;
if (mChart.isDrawBarShadowEnabled()) {
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], mViewPortHandler.contentTop(),
buffer.buffer[j + 2],
mViewPortHandler.contentBottom()), mRadius, mRadius, mShadowPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
if (mRadius > 0)
c.drawRoundRect(new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint);
else
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mRenderPaint);
}
}
}
barChartView.axisLeft.axisMinimum = 0f;
这将使两侧都变成圆形。
我已经基于上述内容为实际库创建了一个类(该类具有不同的绘图代码)- v3.1.0-alpha
class RoundedBarChartRenderer(chart: BarDataProvider,
animator: ChartAnimator,
viewPortHandler: ViewPortHandler,
private val mRadius: Float) :
BarChartRenderer(chart, animator, viewPortHandler) {
private val mBarShadowRectBuffer = RectF()
override fun drawDataSet(c: Canvas?, dataSet: IBarDataSet?, index: Int) {
if (c == null || dataSet == null) return
val trans = mChart.getTransformer(dataSet.axisDependency)
mBarBorderPaint.color = dataSet.barBorderColor
mBarBorderPaint.strokeWidth = Utils.convertDpToPixel(dataSet.barBorderWidth)
val drawBorder = dataSet.barBorderWidth > 0f
val phaseX = mAnimator.phaseX
val phaseY = mAnimator.phaseY
// draw the bar shadow before the values
if (mChart.isDrawBarShadowEnabled) {
mShadowPaint.color = dataSet.barShadowColor
val barData = mChart.barData
val barWidth = barData.barWidth
val barWidthHalf = barWidth / 2.0f
var x: Float
var i = 0
val count = Math.min(Math.ceil((dataSet.entryCount.toFloat() * phaseX).toDouble()).toInt(), dataSet.entryCount)
while (i < count) {
val e = dataSet.getEntryForIndex(i)
x = e.x
mBarShadowRectBuffer.left = x - barWidthHalf
mBarShadowRectBuffer.right = x + barWidthHalf
trans.rectValueToPixel(mBarShadowRectBuffer)
if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right)) {
i++
continue
}
if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
break
mBarShadowRectBuffer.top = mViewPortHandler.contentTop()
mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom()
c.drawRoundRect(mBarRect, mRadius, mRadius, mShadowPaint)
i++
}
}
// initialize the buffer
val buffer = mBarBuffers[index]
buffer.setPhases(phaseX, phaseY)
buffer.setDataSet(index)
buffer.setInverted(mChart.isInverted(dataSet.axisDependency))
buffer.setBarWidth(mChart.barData.barWidth)
buffer.feed(dataSet)
trans.pointValuesToPixel(buffer.buffer)
val isSingleColor = dataSet.colors.size == 1
if (isSingleColor) {
mRenderPaint.color = dataSet.color
}
var j = 0
while (j < buffer.size()) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2])) {
j += 4
continue
}
if (!mViewPortHandler.isInBoundsRight(buffer.buffer[j]))
break
if (!isSingleColor) {
// Set the color for the currently drawn value. If the index
// is out of bounds, reuse colors.
mRenderPaint.color = dataSet.getColor(j / 4)
}
if (dataSet.gradientColor != null) {
val gradientColor = dataSet.gradientColor
mRenderPaint.shader = LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
gradientColor.startColor,
gradientColor.endColor,
android.graphics.Shader.TileMode.MIRROR)
}
if (dataSet.gradientColors != null) {
mRenderPaint.shader = LinearGradient(
buffer.buffer[j],
buffer.buffer[j + 3],
buffer.buffer[j],
buffer.buffer[j + 1],
dataSet.getGradientColor(j / 4).startColor,
dataSet.getGradientColor(j / 4).endColor,
Shader.TileMode.MIRROR)
}
c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mRenderPaint)
if (drawBorder) {
c.drawRoundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius, mRadius, mBarBorderPaint)
}
j += 4
}
}
}
Add the following method to BarChartRenderer
class
/**
* @param rect rectangle to be rounded
* @param rx radius x
* @param ry radius y
* @param tl true - for rounding top-left corner
* @param tr true - for rounding top-right corner
* @param br true - for rounding bottom-right corner
* @param bl true - for rounding bottom-left corner
* @return path
*/
private Path roundRect(RectF rect, float rx, float ry, boolean tl, boolean tr, boolean br, boolean bl) {
float top = rect.top;
float left = rect.left;
float right = rect.right;
float bottom = rect.bottom;
Path path = new Path();
if (rx < 0) rx = 0;
if (ry < 0) ry = 0;
float width = right - left;
float height = bottom - top;
if (rx > width / 2) rx = width / 2;
if (ry > height / 2) ry = height / 2;
float widthMinusCorners = (width - (2 * rx));
float heightMinusCorners = (height - (2 * ry));
path.moveTo(right, top + ry);
if (tr)
path.rQuadTo(0, -ry, -rx, -ry);//top-right corner
else {
path.rLineTo(0, -ry);
path.rLineTo(-rx, 0);
}
path.rLineTo(-widthMinusCorners, 0);
if (tl)
path.rQuadTo(-rx, 0, -rx, ry); //top-left corner
else {
path.rLineTo(-rx, 0);
path.rLineTo(0, ry);
}
path.rLineTo(0, heightMinusCorners);
if (bl)
path.rQuadTo(0, ry, rx, ry);//bottom-left corner
else {
path.rLineTo(0, ry);
path.rLineTo(rx, 0);
}
path.rLineTo(widthMinusCorners, 0);
if (br)
path.rQuadTo(rx, 0, rx, -ry); //bottom-right corner
else {
path.rLineTo(rx, 0);
path.rLineTo(0, -ry);
}
path.rLineTo(0, -heightMinusCorners);
path.close();//Given close, last lineto can be removed.
return path;
}
In drawDataSet(Canvas c, IBarDataSet dataSet, int index)
method, replace all drawRoundRect
methods with the following code
Path path = roundRect(yourRect, yourRadius, yourRadius, true, true, false, false);
canvas.drawPath(path, yourPaint);
有了@duc tan的答案,我解决了这个问题,但他的代码没有处理高亮。我添加了以下代码来解决高亮角落。
public void drawHighlighted(Canvas c, Highlight[] indices) {
BarData barData = mChart.getBarData();
for (Highlight high : indices) {
IBarDataSet set = barData.getDataSetByIndex(high.getDataSetIndex());
if (set == null || !set.isHighlightEnabled()) {
continue;
}
BarEntry e = set.getEntryForXValue(high.getX(), high.getY());
if (!isInBoundsX(e, set)) {
continue;
}
Transformer trans = mChart.getTransformer(set.getAxisDependency());
mHighlightPaint.setColor(set.getHighLightColor());
mHighlightPaint.setAlpha(set.getHighLightAlpha());
boolean isStack = high.getStackIndex() >= 0 && e.isStacked();
final float y1;
final float y2;
if (isStack) {
if (mChart.isHighlightFullBarEnabled()) {
y1 = e.getPositiveSum();
y2 = -e.getNegativeSum();
} else {
Range range = e.getRanges()[high.getStackIndex()];
y1 = range.from;
y2 = range.to;
}
} else {
y1 = e.getY();
y2 = 0.f;
}
prepareBarHighlight(e.getX(), y1, y2, barData.getBarWidth() / 2f, trans);
setHighlightDrawPos(high, mBarRect);
Path path2 = roundRect(new RectF(mBarRect.left, mBarRect.top, mBarRect.right,
mBarRect.bottom), mRadius, mRadius, true, true, false, false);
c.drawPath(path2, mHighlightPaint);
}
}