2012-01-27 27 views
21

Estoy tratando de crear un arco (número variable de grados) que vaya gradualmente de un color a otro. Del ejemplo de azul a rojo:

enter image description hereAndroid - Cómo dibujar un degradado basado en arco

Este es mi código:

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

Pero el resultado es todo el arco está pintado con el mismo color.

Editar:
Después de más experimentación, descubrí que el color propagación está determinada por el ángulo del arco. Si dibujo un arco con un pequeño ángulo, solo se muestra el primer color. Cuanto mayor es el ángulo, más colores se dibujan. Si el ángulo es pequeño, parece que no hay gradiente.
Aquí hay un ejemplo. Estoy dibujando arcos 4 - 90, 180, 270 y 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); 

Y aquí está el resultado:

enter image description here

Esto es sorprendente porque yo esperaría que el ROJO para estar en el el comienzo del arco, el AZUL al final y el enything intermedio para repartir uniformemente sin importar el ángulo.
Me trataron de espacio de los colores de forma manual utilizando el parámetro de posiciones, pero los resultados fueron los mismos:

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

alguna idea de cómo resolver esto?

Respuesta

27

La solución para esto es establecer la posición de AZUL. Esto se hace de la siguiente manera:

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

El problema aquí es que al establecer la posición de AZUL a '1' Esto no quiere decir que se coloca en el extremo del arco dibujado, pero en su lugar al final del círculo del cual el arco es parte. Para resolver esto, la posición AZUL debe tener en cuenta el número de grados en el arco. Así que si estoy dibujando un arco con X grados, la posición se puede ajustar de este modo:

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

Así que si X es 90, el gradiente colocará BLUE en 0,25 del círculo:

enter image description here

+1

Al menos en Android 4.2, la solución dada no funciona.Hay una necesidad de tener un valor de 1 al final de la matriz. Algo como esto: int [] colors = {Color.RED, Color.BLUE, Color.BLUE}; flotante [] posiciones = {0, Xf/360f, 1}; –

+0

¿Sabes por qué la resolución es tan mala si el ángulo es muy pequeño? como un ancho de arco de 10 grados significa solo 3 colores. Puede ver los pasos también en su captura de pantalla en la torta topleft –

9

Para agregar a la solución de Yoav.

En mi Galaxy Nexus 4.2 stock Android, la solución proporcionada no funciona.

Si la matriz no contiene un 0.0f y 1.0f, parece ser ignorada.

Mi solución final fue:

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

cinco años más tarde, pero la manera correcta es hacer 0.749f con 0.750f de la línea separada, código simple es como:

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

gracias por publicar Kotlin – rundavidrun

Cuestiones relacionadas