【问题标题】:How to get programmatically a list of colors from a gradient on Android如何以编程方式从 Android 上的渐变中获取颜色列表
【发布时间】:2011-12-08 10:34:35
【问题描述】:

在 Android 中,我想绘制一个带有动态数量的饼图的 PieChart。每个饼图的颜色应该与渐变不同。

例如,我想要从浅棕色到深棕色的渐变。如果我需要画五个馅饼,我需要从这个渐变的开始到结束的五个卷。

如何使用 Android 框架在 Java 中做到这一点?

我发现我可以为一条线创建一个 LinearGradient,即:

LinearGradient lg = new LinearGradient(1, 1, 5, 5, toRGB("lightbrown"), toRGB("darkbrown"), TileMode.REPEAT);

但我没有找到任何函数可以从这一行获取颜色,即:

// 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);

你有什么想法我可以得到这个吗?

谢谢!

【问题讨论】:

    标签: android list colors gradient


    【解决方案1】:

    您无法直接从 LinearGradient 获取这些值。渐变不包含实际绘图。要获得这些值,您可以将它们绘制到画布上并从画布中提取颜色,或者我建议您自己计算这些值。

    这是一个重复的五步线性渐变,您可以获取第一种和最后一种颜色的 RGB 值。剩下的只是数学。这是伪代码:

    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);
    

    【讨论】:

    • 感谢您提出这个简单而伟大的想法!
    【解决方案2】:

    另一种更可重用的方法(我似乎一直遇到这个问题)。这是更多的代码。用法如下:

        int[] colors = {toRGB("lightbrown"), toRGB("darkbrown")};//assuming toRGB : String -> Int
        float[] positions = {1, 5};
        getColorFromGradient( colors, positions, 1 )
        //...
        getColorFromGradient( colors, positions, 5 )
    

    支持功能

    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);
    }
    

    【讨论】:

    • 对动态计算很有用
    【解决方案3】:

    我已经编写了用于计算颜色渐变的 util 类。

    通过非常非常简单的 Kotlin 代码:

        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}
        }
    

    支持 util 类

     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 repo 上的完整源代码示例

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-04-15
      • 1970-01-01
      • 2016-12-28
      • 2016-05-20
      • 2014-05-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多