Skip to content

Instantly share code, notes, and snippets.

@timtsj
Created October 5, 2020 04:19
Show Gist options
  • Save timtsj/28e0da04b2037d7988e266636e10a277 to your computer and use it in GitHub Desktop.
Save timtsj/28e0da04b2037d7988e266636e10a277 to your computer and use it in GitHub Desktop.
mpandroidchart stacked bar chart radius
package com.exmaple
import android.graphics.*
import com.github.mikephil.charting.animation.ChartAnimator
import com.github.mikephil.charting.interfaces.dataprovider.BarDataProvider
import com.github.mikephil.charting.interfaces.datasets.IBarDataSet
import com.github.mikephil.charting.renderer.BarChartRenderer
import com.github.mikephil.charting.utils.Utils
import com.github.mikephil.charting.utils.ViewPortHandler
class RoundBarChartRender(
chart: BarDataProvider?,
animator: ChartAnimator?,
viewPortHandler: ViewPortHandler?
) : BarChartRenderer(chart, animator, viewPortHandler) {
private val mBarShadowRectBuffer = RectF()
private var mRadius = 0
fun setRadius(mRadius: Int) {
this.mRadius = mRadius
}
override fun drawDataSet(c: Canvas, dataSet: IBarDataSet, index: Int) {
val trans = mChart.getTransformer(dataSet.axisDependency)
mBarBorderPaint.color = dataSet.barBorderColor
mBarBorderPaint.strokeWidth = Utils.convertDpToPixel(dataSet.barBorderWidth)
mShadowPaint.color = dataSet.barShadowColor
val drawBorder = dataSet.barBorderWidth > 0f
val phaseX = mAnimator.phaseX
val phaseY = mAnimator.phaseY
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()), dataSet.entryCount.toDouble())
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.toFloat(), mRadius.toFloat(), 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
}
for (j in (0..buffer.size() - 4).reversed() step 4) {
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.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,
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)
}
val path2 = roundRect(
RectF(
buffer.buffer[j],
buffer.buffer[j + 1],
buffer.buffer[j + 2],
buffer.buffer[j + 3]
),
mRadius.toFloat(),
mRadius.toFloat(),
true,
true,
false,
false
)
c.drawPath(path2, mRenderPaint)
if (drawBorder) {
val path = roundRect(RectF(buffer.buffer[j], buffer.buffer[j + 1], buffer.buffer[j + 2],
buffer.buffer[j + 3]), mRadius.toFloat(), mRadius.toFloat(), true, true, false, false)
c.drawPath(path, mBarBorderPaint)
}
}
}
private fun roundRect(rect: RectF, rx: Float, ry: Float, tl: Boolean, tr: Boolean, br: Boolean, bl: Boolean): Path {
var rx = rx
var ry = ry
val top = rect.top
val left = rect.left
val right = rect.right
val bottom = rect.bottom
val path = Path()
if (rx < 0) rx = 0f
if (ry < 0) ry = 0f
val width = right - left
val height = bottom - top
if (rx > width / 2) rx = width / 2
if (ry > height / 2) ry = height / 2
val widthMinusCorners = width - 2 * rx
val heightMinusCorners = height - 2 * ry
path.moveTo(right, top + ry)
if (tr) path.rQuadTo(0f, -ry, -rx, -ry) //top-right corner
else {
path.rLineTo(0f, -ry)
path.rLineTo(-rx, 0f)
}
path.rLineTo(-widthMinusCorners, 0f)
if (tl) path.rQuadTo(-rx, 0f, -rx, ry) //top-left corner
else {
path.rLineTo(-rx, 0f)
path.rLineTo(0f, ry)
}
path.rLineTo(0f, heightMinusCorners)
if (bl) path.rQuadTo(0f, ry, rx, ry) //bottom-left corner
else {
path.rLineTo(0f, ry + mRadius)
path.rLineTo(rx, 0f)
}
path.rLineTo(widthMinusCorners, 0f)
if (br) path.rQuadTo(rx, 0f, rx, -ry) //bottom-right corner
else {
path.rLineTo(rx, 0f)
path.rLineTo(0f, -ry)
}
path.rLineTo(0f, -heightMinusCorners)
path.close() //Given close, last lineto can be removed.
return path
}
}
@rajandxfactor
Copy link

Hi With using the above code we are getting the below result
Issues_MP_Android_Chart

Any clues while like that bottom Curve for 0 values?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment