in Android I would like to draw a PieChart with a dynamically number of pies. Each pie should have a different color from a gradient.
For example I would like to have a gradient from light brown to dark brown. If I need to draw five pies, I need five volors from the start to the end of this gradient.
How can I do that in Java with the Android framework?
I found out that I can create a LinearGradient for a line, i.e.:
LinearGradient lg = new LinearGradient(1, 1, 5, 5, toRGB("lightbrown"), toRGB("darkbrown"), TileMode.REPEAT);
But I did not found any function to get a color from this line, i.e.:
// for the five needed RGB colors from the gradient line
lg.getRGBColor(1, 1);
lg.getRGBColor(2, 2);
lg.getRGBColor(3, 3);
lg.getRGBColor(4, 4);
lg.getRGBColor(5, 5);
Do you have any ideas how I can get this?
Thanks!
You cannot get these values directly from the LinearGradient. The gradient doesn't contain the actual drawing. To get these values, you can paint them to a canvas and pull the colors out of the canvas, or what I'd suggest would be to calculate the values yourself.
It's a repeating linear gradient in five steps and you have the RGB values for the first and last color. The rest is just math. Here's the pseudo code:
int r1 = startColor.red;
int g1 = startColor.green;
int b1 = startColor.blue;
int r2 = endColor.red;
int g2 = endColor.green;
int b2 = endColor.blue;
int redStep = r2 - r1 / 4;
int greenStep = g2 - g1 / 4;
int blueStep = b2 - b1 / 4;
firstColor = new Color(r1, g1, b1);
secondColor = new Color(r1 + redStep, g1 + greenStep, b1 + blueStep);
thirdColor = new Color(r1 + redStep * 2, g1 + greenStep * 2, b1 + blueStep * 2);
fourthColor = new Color(r1 + redStep * 3, g1 + greenStep * 3, b1 + blueStep * 3);
fifthColor = new Color(r1 + redStep * 4, g1 + greenStep * 4, b1 + blueStep * 4);
Another approach that is a little more reusable (I seem to bump into this problem all the time). It's a bit more code. Here is the usage:
int[] colors = {toRGB("lightbrown"), toRGB("darkbrown")};//assuming toRGB : String -> Int
float[] positions = {1, 5};
getColorFromGradient( colors, positions, 1 )
//...
getColorFromGradient( colors, positions, 5 )
Supporting functions
public static int getColorFromGradient(int[] colors, float[] positions, float v ){
if( colors.length == 0 || colors.length != positions.length ){
throw new IllegalArgumentException();
}
if( colors.length == 1 ){
return colors[0];
}
if( v <= positions[0]) {
return colors[0];
}
if( v >= positions[positions.length-1]) {
return colors[positions.length-1];
}
for( int i = 1; i < positions.length; ++i ){
if( v <= positions[i] ){
float t = (v - positions[i-1]) / (positions[i] - positions[i-1]);
return lerpColor(colors[i-1], colors[i], t);
}
}
//should never make it here
throw new RuntimeException();
}
public static int lerpColor( int colorA, int colorB, float t){
int alpha = (int)Math.floor(Color.alpha(colorA) * ( 1 - t ) + Color.alpha(colorB) * t);
int red = (int)Math.floor(Color.red(colorA) * ( 1 - t ) + Color.red(colorB) * t);
int green = (int)Math.floor(Color.green(colorA) * ( 1 - t ) + Color.green(colorB) * t);
int blue = (int)Math.floor(Color.blue(colorA) * ( 1 - t ) + Color.blue(colorB) * t);
return Color.argb(alpha, red, green, blue);
}
I have wrote the util class for calculate colors gradient.
via very, very simple Kotlin code:
val pink = Colar(245, 9, 253)
val lime = Colar(0, 253, 32)
lp_1.colors = (pink toColor lime).run {
gradient { 0 upTo 3 }
}
lp_2.colors = (pink toColor lime).run {
gradient { 0 upTo 9 }
}
lp_3.colors = (pink toColor lime).run {
gradient { 3 upTo 9}
}
Supporting util class
class StepGradientUtil(private var colar1: Colar?, private var colar2: Colar?) {
private var mSteps: Int = 0
infix fun StepGradientUtil.gradient(f: () -> IntRange): IntArray {
val result = f.invoke().map {
it.colorStep()
}.toIntArray()
recycler()
return result
}
infix fun Int.upTo(steps: Int): IntRange {
mSteps = steps
return (this until steps)
}
private fun recycler() {
mSteps = 0
colar1 = null
colar2 = null
}
private fun Int.colorStep() = Color.rgb(
(colar1!!.r * (mSteps - this) + colar2!!.r * this) / mSteps,
(colar1!!.g * (mSteps - this) + colar2!!.g * this) / mSteps,
(colar1!!.b * (mSteps - this) + colar2!!.b * this) / mSteps
)
}
data class Colar(
val r: Int,
val g: Int,
val b: Int
)
infix fun Colar.toColor(colar: Colar) = StepGradientUtil(colar1 = this, colar2 = colar)
See full source code sample on repo
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With