2012-01-27 25 views
21

Sto provando a creare un arco (numero variabile di gradi) che passa gradualmente da un colore all'altro. Dall'esempio dal blu al rosso:

enter image description hereAndroid - Come disegnare un gradiente ad arco

Questo è il mio codice:

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

Ma il risultato è l'intero arco è dipinto con lo stesso colore.

Edit:
Dopo più sperimentazione, ho scoperto che la diffusione colore è determinato dall'angolo dell'arco. Se disegno un arco con un angolo piccolo, viene visualizzato solo il primo colore. Più grande è l'angolo, più colori vengono disegnati. Se l'angolo è piccolo sembra che non ci sia un gradiente.
Ecco un esempio. Sto disegnando archi 4 - 90, 180, 270 e 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); 

Ed ecco il risultato:

enter image description here

Ciò è sorprendente, perché mi aspetto il RED di essere al inizio dell'arco, il BLU alla fine e tutto ciò che deve essere sparso uniformemente indipendentemente dall'angolo.
Ho cercato di spazio i colori manualmente utilizzando il parametro posizioni, ma i risultati erano gli stessi:

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

Qualsiasi idea di come risolvere questo?

risposta

27

La soluzione per questo è impostare la posizione di BLU. Questo viene fatto in questo modo:

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

Il problema è che quando si imposta la posizione di BLU a '1' questo non significa che sarà posizionato all'estremità dell'arco disegnata, ma invece alla fine del cerchio di cui fa parte l'arco. Per risolvere questo, la posizione BLU dovrebbe tenere conto del numero di gradi nell'arco. Quindi, se io sto disegnando un arco con X gradi, la posizione verrà impostata in questo modo:

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

Quindi, se X è 90, il gradiente metterà BLU allo 0,25 del cerchio:

enter image description here

+1

Almeno su Android 4.2, la soluzione come data non funziona.È necessario avere un valore pari a 1 alla fine dell'array. Qualcosa del genere: int [] colors = {Color.RED, Color.BLUE, Color.BLUE}; float [] posizioni = {0, Xf/360f, 1}; –

+0

Sai perché la risoluzione è così grave se l'angolo è molto piccolo? come una larghezza dell'arco di 10 gradi significa solo 3 colori. Puoi vedere i passaggi anche nel tuo screenshot nella torta di topleft –

9

Da aggiungere alla soluzione di Yoav.

Sul mio Android Galaxy Nexus 4.2, la soluzione indicata non funziona.

Se la matrice non contiene 0,0f e 1,0f, sembra essere ignorata.

La mia soluzione finale è stata:

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

cinque anni più tardi, ma la strada giusta è fare 0.749f con 0.750f della linea separata, semplice codice è come:

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

grazie per aver postato Kotlin – rundavidrun

Problemi correlati