本来设计图,方方正正的柱图不好嘛~非要加一些奇奇怪怪的需求0-0
先上图:
需求大概就是需要渐变色,又要下面底平,上面是圆头的。
正常我们在官方例子里面,我们可以知道.
BarDataSet set1;
set1.setFills(gradientFills);
这样就可以设置渐变色了,但是这里有一个坑需要注意的是,如果是implementation V3.1
的版本,这个方法会不存在,所以需要下载源代码然后到自己的库里面去。
OK,好了,剩下就是圆头的事情了。
众所周知,BarChart画画的事情,主要跟它的渲染器有问题,所以去设置渲染器就可以了。
BarChart有个专门做倒角的渲染器.RoundedBarChartRenderer
RoundedBarChartRenderer roundedBarChartRenderer = new RoundedBarChartRenderer(gBarChart,gBarChart.getAnimator(),gBarChart.getViewPortHandler());
roundedBarChartRenderer.setmRadius(20f);
gBarChart.setRenderer(roundedBarChartRenderer);
但是发现问题:这个圆角是四个角,不符合我们的需求啊~
然后去找BarChartRender类把,画图方法是drawDataSet,我们进行重写它,发现正常走的是drawRect,所以修改它,用Path画出自己需要的图案.
RectF r2 = new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]);
Path path = new Path();
path.addRoundRect(r2, new float[]{50, 50, 50, 50, 0, 0, 0, 0}, Path.Direction.CCW);
c.drawPath(path, mRenderPaint);
但是又出现另外一个问题,发现有渐变的时候,走的位置是另外的方法.
dataSet.getFill(pos)
.fillRect(
c, mRenderPaint,
buffer.buffer[j],
buffer.buffer[j + 1],
buffer.buffer[j + 2],
buffer.buffer[j + 3],
isInverted ? Fill.Direction.DOWN : Fill.Direction.UP);
OK,我们进到dataSet.getFill(pos).fillRect()
方法,发现执行的也是drawRect方法。
之后我们进行修改可以了。
添加一个xRender类继承BarChartRenderer ,并重写drawDataSet方法,完整的Render
public class xRender extends BarChartRenderer {
private RectF mBarShadowRectBuffer = new RectF();
public xRender(BarDataProvider chart, ChartAnimator animator, ViewPortHandler viewPortHandler) {
super(chart, animator, viewPortHandler);
this.mChart = chart;
mHighlightPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mHighlightPaint.setColor(Color.rgb(0, 0, 0));
mHighlightPaint.setAlpha(120);
mShadowPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mShadowPaint.setStyle(Paint.Style.FILL);
mBarBorderPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
mBarBorderPaint.setStyle(Paint.Style.STROKE);
}
@Override
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()));
final boolean drawBorder = dataSet.getBarBorderWidth() > 0.f;
float phaseX = mAnimator.getPhaseX();
float phaseY = mAnimator.getPhaseY();
// draw the bar shadow before the values
if (mChart.isDrawBarShadowEnabled()) {
mShadowPaint.setColor(dataSet.getBarShadowColor());
BarData barData = mChart.getBarData();
final float barWidth = barData.getBarWidth();
final float barWidthHalf = barWidth / 2.0f;
float x;
for (int i = 0, count = Math.min((int)(Math.ceil((float)(dataSet.getEntryCount()) * phaseX)), dataSet.getEntryCount());
i < count;
i++) {
BarEntry e = dataSet.getEntryForIndex(i);
x = e.getX();
mBarShadowRectBuffer.left = x - barWidthHalf;
mBarShadowRectBuffer.right = x + barWidthHalf;
trans.rectValueToPixel(mBarShadowRectBuffer);
if (!mViewPortHandler.isInBoundsLeft(mBarShadowRectBuffer.right))
continue;
if (!mViewPortHandler.isInBoundsRight(mBarShadowRectBuffer.left))
break;
mBarShadowRectBuffer.top = mViewPortHandler.contentTop();
mBarShadowRectBuffer.bottom = mViewPortHandler.contentBottom();
c.drawRect(mBarShadowRectBuffer, mShadowPaint);
}
}
// 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);
final boolean isCustomFill = dataSet.getFills() != null && !dataSet.getFills().isEmpty();
final boolean isSingleColor = dataSet.getColors().size() == 1;
final boolean isInverted = mChart.isInverted(dataSet.getAxisDependency());
if (isSingleColor) {
mRenderPaint.setColor(dataSet.getColor());
}
for (int j = 0, pos = 0; j < buffer.size(); j += 4, pos++) {
if (!mViewPortHandler.isInBoundsLeft(buffer.buffer[j + 2]))
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(pos));
}
if (isCustomFill) {
dataSet.getFill(pos)
.fillRectx(
c, mRenderPaint,
buffer.buffer[j],
buffer.buffer[j + 1],
buffer.buffer[j + 2],
buffer.buffer[j + 3],
isInverted ? Fill.Direction.DOWN : Fill.Direction.UP);
}else {
RectF r2 = new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]);
Path path = new Path();
//float数组中4个角分别是左上、右上、右下、左下
path.addRoundRect(r2, new float[]{50, 50, 50, 50, 0, 0, 0, 0}, Path.Direction.CCW);
c.drawPath(path, mRenderPaint);
}
//c.drawRoundRect(r2,50,10,mRenderPaint);
// c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
// buffer.buffer[j + 3], mRenderPaint);
if (drawBorder) {
c.drawRect(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3], mBarBorderPaint);
}
}
}
/**
* 手指点击的半透明灰色修改
* */
@Override
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()) ? true : false;
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);
// c.drawRect(mBarRect, mHighlightPaint); 原父类方法
Path path = new Path();
//float数组中4个角分别是左上、右上、右下、左下
path.addRoundRect(mBarRect,new float[]{50, 50, 50, 50, 0, 0, 0, 0},Path.Direction.CCW);
c.drawPath(path,mHighlightPaint);
}
}
}
在点进去的dataSet.getFill(pos).fillRect()
方法添加以下方法。
public void fillRectx(Canvas c, Paint paint,
float left, float top, float right, float bottom,
Direction gradientDirection)
{
switch (mType)
{
case EMPTY:
return;
case COLOR:
{
if (mFinalColor == null) return;
if (isClipPathSupported())
{
int save = c.save();
c.clipRect(left, top, right, bottom);
c.drawColor(mFinalColor);
c.restoreToCount(save);
}
else
{
// save
Paint.Style previous = paint.getStyle();
int previousColor = paint.getColor();
// set
paint.setStyle(Paint.Style.FILL);
paint.setColor(mFinalColor);
c.drawRect(left, top, right, bottom, paint);
// restore
paint.setColor(previousColor);
paint.setStyle(previous);
}
}
break;
case LINEAR_GRADIENT:
{
if (mGradientColors == null) return;
LinearGradient gradient = new LinearGradient(
(int) (gradientDirection == Direction.RIGHT
? right
: gradientDirection == Direction.LEFT
? left
: left),
(int) (gradientDirection == Direction.UP
? bottom
: gradientDirection == Direction.DOWN
? top
: top),
(int) (gradientDirection == Direction.RIGHT
? left
: gradientDirection == Direction.LEFT
? right
: left),
(int) (gradientDirection == Direction.UP
? top
: gradientDirection == Direction.DOWN
? bottom
: top),
mGradientColors,
mGradientPositions,
android.graphics.Shader.TileMode.MIRROR);
paint.setShader(gradient);
RectF r2 = new RectF(left, top,right,
bottom);
Path path = new Path();
//float数组中4个角分别是左上、右上、右下、左下
path.addRoundRect(r2, new float[]{50, 50, 50, 50, 0, 0, 0, 0}, Path.Direction.CCW);
c.drawPath(path, paint);
}
break;
case DRAWABLE:
{
if (mDrawable == null) return;
mDrawable.setBounds((int) left, (int) top, (int) right, (int) bottom);
mDrawable.draw(c);
}
break;
}
}
使用:搞定~
xRender roundedBarChartRenderer = new xRender(gBarChart,gBarChart.getAnimator(),gBarChart.getViewPortHandler());
gBarChart.setRenderer(roundedBarChartRenderer);
这可真是一个神奇的框架~~~
画一个自定义死角弧度的Path:
https://blog.csdn.net/qq_40129067/article/details/108799871
RectF rectF=new RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],buffer.buffer[j + 3]);
Path path = new Path();
//float数组中4个角分别是左上、右上、右下、左下
path.addRoundRect(rectF,new float[]{0, 0, 20, 20, 20, 20, 0, 0},Path.Direction.CCW);
c.drawPath(path,mRenderPaint);