【问题标题】:Android - How to draw an arc based gradientAndroid - 如何绘制基于弧的渐变
【发布时间】:2012-02-20 16:00:59
【问题描述】:

我正在尝试创建一个逐渐从一种颜色变为另一种颜色的弧(可变度数)。从蓝色到红色的示例:

这是我的代码:

SweepGradient shader = new SweepGradient(center.x, center.y, resources.getColor(R.color.startColor),resources.getColor(R.color.endColor));
Paint paint = new Paint()
paint.setStrokeWidth(1);
paint.setStrokeCap(Paint.Cap.FILL);
paint.setStyle(Paint.Style.FILL);
paint.setShader(shader);
canvas.drawArc(rectF, startAngle, sweepAngle, true, paint);

但结果是整个弧线都涂上了相同的颜色。

编辑:
经过更多的实验,我发现颜色扩散是由圆弧的角度决定的。如果我画一个小角度的圆弧,只显示第一种颜色。角度越大,绘制的颜色就越多。如果角度很小,似乎没有渐变。
这是一个例子。我正在绘制 4 条弧线 - 90、180、270 和 360:

RectF rect1 = new RectF(50, 50, 150, 150);
Paint paint1 = new Paint();
paint1.setStrokeWidth(1);
paint1.setStrokeCap(Paint.Cap.SQUARE);
paint1.setStyle(Paint.Style.FILL);

SweepGradient gradient1 = new SweepGradient(100, 100,
        Color.RED, Color.BLUE);
paint1.setShader(gradient1);

canvas.drawArc(rect1, 0, 90, true, paint1);

RectF rect2 = new RectF(200, 50, 300, 150);
Paint paint2 = new Paint();
paint2.setStrokeWidth(1);
paint2.setStrokeCap(Paint.Cap.SQUARE);
paint2.setStyle(Paint.Style.FILL);

SweepGradient gradient2 = new SweepGradient(250, 100,
        Color.RED, Color.BLUE);
paint2.setShader(gradient2);

canvas.drawArc(rect2, 0, 180, true, paint2);

RectF rect3 = new RectF(50, 200, 150, 300);
Paint paint3 = new Paint();
paint3.setStrokeWidth(1);
paint3.setStrokeCap(Paint.Cap.SQUARE);
paint3.setStyle(Paint.Style.FILL);

SweepGradient gradient3 = new SweepGradient(100, 250,
        Color.RED, Color.BLUE);
paint3.setShader(gradient3);

canvas.drawArc(rect3, 0, 270, true, paint3);

RectF rect4 = new RectF(200, 200, 300, 300);
Paint paint4 = new Paint();
paint4.setStrokeWidth(1);
paint4.setStrokeCap(Paint.Cap.SQUARE);
paint4.setStyle(Paint.Style.FILL);

SweepGradient gradient4 = new SweepGradient(250, 250,
        Color.RED, Color.BLUE);
paint4.setShader(gradient4);

canvas.drawArc(rect4, 0, 360, true, paint4);

结果如下:

这令人惊讶,因为我希望红色位于弧线的起点,蓝色位于弧线的末端,并且无论角度如何,两者之间的任何东西都会均匀分布。
我尝试使用位置参数手动分隔颜色,但结果相同:

int[] colors = {Color.RED, Color.BLUE};
float[] positions = {0,1};
SweepGradient gradient = new SweepGradient(100, 100, colors , positions);

知道如何解决这个问题吗?

【问题讨论】:

    标签: android graphics 2d geometric-arc


    【解决方案1】:

    解决办法是设置BLUE的位置。这样做是这样的:

    int[] colors = {Color.RED, Color.BLUE};
    float[] positions = {0,1};
    SweepGradient gradient = new SweepGradient(100, 100, colors , positions);
    

    这里的问题是,当设置 BLUE 的位置为 '1' 时,这并不意味着它将定位在绘制的圆弧的末端,而是位于圆弧所在的圆的末端. 为了解决这个问题,BLUE 位置应该考虑弧度数。因此,如果我正在绘制 X 度的圆弧,则位置将设置如下:

    float[] positions = {0,Xf/360f};
    

    所以如果 X 为 90,渐变将 BLUE 放置在圆的 0.25 处:

    【讨论】:

    • 至少在 Android 4.2 上,给定的解决方案不起作用。需要在数组末尾有一个值 1。像这样的东西: int[] colors = {Color.RED, Color.BLUE, Color.BLUE};浮动[] 位置 = {0, Xf/360f, 1};
    • 你知道为什么角度很小分辨率那么差吗?就像 10 度的弧宽意味着只有 3 种颜色。您也可以在左上角蛋糕的屏幕截图中看到这些步骤
    【解决方案2】:

    添加到 Yoav 的解决方案中。

    在我的 Galaxy Nexus 4.2 库存 Android 上,给出的解决方案不起作用。

    如果数组不包含 0.0f 和 1.0f,它似乎被忽略了。

    我的最终解决方案是:

    int[] colors = {Color.RED, Color.BLUE, Color.RED}; 
    float[] positions = {0, Xf/360f, 1};
    

    【讨论】:

      【解决方案3】:

      五年后,但正确的做法是把0.749f和0.750f分开行,简单的代码是这样的:

          val colors = intArrayOf(0xffff0000.toInt(), 0xff0000ff.toInt(), 0xffff0000.toInt(), 0xffff0000.toInt())
          val positions = floatArrayOf(0.0f, 0.749f, 0.750f, 1.0f)
      

      【讨论】:

        【解决方案4】:

        使用SweepGradient,您可以将null 传递给位置(如果您需要默认渐变),您还可以通过setLocalMatrix 旋转渐变

        override fun onDraw(canvas: Canvas?) {
            super.onDraw(canvas)
            val centerX = width.toFloat() / 2
            val centerY = height.toFloat() / 2
        
            val paint = Paint()
            paint.isAntiAlias = true
        
            val colors = intArrayOf(Color.RED, Color.BLUE)
            val gradient = SweepGradient(centerX, centerY, colors, null) // null position
            val matrix = Matrix()
            matrix.postRotate(270f, centerX, centerY) // rotate
            gradient.setLocalMatrix(matrix)
            paint.shader = gradient
        
            val radius = 400f
            val oval = RectF(centerX - radius,centerY - radius,centerX + radius,centerY + radius)
            canvas?.drawArc(oval, 0f, 360f, false, paint)
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-07-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-01-03
          • 1970-01-01
          相关资源
          最近更新 更多