2011-01-18 22 views
9

Necesito pintar el fondo de mi lienzo de un color con sombreado/degradado aplicado, pero cada llamada a un disco me gustaría potencialmente cambiar el color.Cómo pintar un degradado de color en Android en un lienzo con el cambio de color?

Tengo problemas para hacer esto sin crear un objeto nuevo cada llamada deDraw. ¿Alguien tiene alguna idea? Si uso drawPaint() y establezco un nuevo shader() en mi pintura, entonces he creado un nuevo objeto shader y si creo un nuevo GradientDrawable() tengo también. Quiero evitar GC.

Pensé que podría reutilizar un objeto GradientDrawable() y llamar al método .setColor(), pero esto solo restablece los datos de gradiente asociados y pinta el dibujable como ese color sólido.

¿Alguien?

Respuesta

5

Lamentablemente debe crear un nuevo LinearGradient cada vez. Tenga en cuenta que no tiene que usar un GradientDrawable, puede dibujar la forma usted mismo con una pintura en la que configure el sombreador.

+0

Gracias Romain, ¿podría compartir su experiencia en mi comentario a campnic a continuación? Me pregunto cuál sería el método .draw ...() más eficiente para dibujar las dos capas requeridas para crear este efecto o si LayerDrawable es exactamente lo que necesito. – Greg

+0

@Romain Guy He estado tratando de usar SweepGradient para lograr un efecto de gradiente cónico.Pero parece funcionar solo con dos colores. Si utilizo una matriz de cuatro colores, ** SweepGradient ** no parece funcionar como se esperaba. Probé varias combinaciones de valores de ** posiciones ** y también intenté las posiciones de configuración como ** NULL ** pero la mayoría obtuve solo dos colores o un degradado que no es cónico. Cualquier ayuda sería muy apreciada. –

0

Creo que lo que quieres hacer es esto. Cree un LayerDrawable y luego inserte dos Drawables en él. El primer Drawable que inserte debe tener su color configurado para el color que desea que tenga su fondo y el segundo debe ser un Gradiente configurado para ser negro y la transición de alfa 0 a alpha 255.

Para obtener más información información, consulte: http://developer.android.com/guide/topics/resources/drawable-resource.html#LayerList

+0

campnic - gracias, esto es una especie de lo que estaba buscando cuando pensé llamar canvas.drawARGB() con alpha xFF y luego una pintura con sombreado o gradiente con alfa menor encima. Solo estoy preocupado por la eficiencia. Quería evitar dibujar todo el lienzo con dos capas y quería saber si había una construcción incorporada para hacer esto de una vez. ¿El LayerDrawable logra esto o hace un dibujo secuencial capa por capa? – Greg

+0

Hice un poco de excavación, y lo que estoy viendo sugiere que terminarás dibujando dos capas completas en toda la pantalla. El código para LayerDrawable.draw simplemente itera sobre los Dratables infantiles en orden de índice descendente. Creo que el rendimiento de LayerDRawable puede no ser el que quieres usar. Romain tiene mucha más experiencia con estas cosas, por lo que probablemente pueda darle una mejor idea :) –

+0

Realmente aprecio que mire esto, esto es lo que también encontré y sospeché al revisar la documentación. Tendré que pensar en algo creativo para un buen fondo de aspecto dinámico si no hay una solución integrada. – Greg

0

Esta pregunta todavía es válida casi a mediados de 2017. Quería crear una transición sin problemas para los cambios de color de mi vista personalizada. Usé shaders con LinearGradients.

Mi intención era hacer una transición fluida entre el estado de mi vista y el de mi vista.

Mi caso es aún más complicado debido a la construcción y el propósito de la vista. Es un control deslizante. Entonces mi vista consiste en casi 2 capas idénticas dibujadas una encima de la segunda usando lienzo. El tercer elemento es un puntero.

Ambas capas usan LinearGradients, el puntero usa un solo color.

Resumiendo todo lo que tengo que hacer una transición entre 5 colores al mismo tiempo:

  • de inicio y final de color para la capa inferior - uno LinearGradient,
  • inicio y el final del color de la capa superior - segundo LinearGradient ,
  • color del puntero - color normal;

La solución a esto es tener 5 ValueAnimators separados. Lo más importante es utilizar ValueAnimator.ofArgb():

private ValueAnimator frontStartColorAnimator; 
private ValueAnimator frontEndColorAnimator; 
private ValueAnimator bottomStartColorAnimator; 
private ValueAnimator bottomEndColorAnimator; 
private ValueAnimator pointerColorAnimator; 
private AnimatorSet colorsAnimatorSet; 

... 

frontStartColorAnimator = ValueAnimator.ofArgb(frontLayerStartColor, frontLayerDisabledStartColor); 
frontStartColorAnimator.setDuration(animationDuration); 
frontStartColorAnimator.setInterpolator(new LinearInterpolator()); 
frontStartColorAnimator.addUpdateListener(animation 
      -> shaderFrontLayerStartColor = (int) animation.getAnimatedValue()); 

frontEndColorAnimator = ValueAnimator.ofArgb(frontLayerEndColor, frontLayerDisabledEndColor); 
frontEndColorAnimator.setDuration(animationDuration); 
frontEndColorAnimator.setInterpolator(new LinearInterpolator()); 
frontEndColorAnimator.addUpdateListener(animation -> { 
     shaderFrontLayerEndColor = (int) animation.getAnimatedValue(); 
     frontLayerPaint.setShader(new LinearGradient(0, 0, getWidth(), 0, shaderFrontLayerStartColor, 
       shaderFrontLayerEndColor, Shader.TileMode.CLAMP)); 
    }); 

bottomStartColorAnimator = ValueAnimator.ofArgb(bottomLayerStartColor, bottomLayerDisabledStartColor); 
bottomStartColorAnimator.setDuration(animationDuration); 
bottomStartColorAnimator.setInterpolator(new LinearInterpolator()); 
bottomStartColorAnimator.addUpdateListener(animation -> 
      shaderBottomLayerStartColor = (int) animation.getAnimatedValue()); 

bottomEndColorAnimator = ValueAnimator.ofArgb(bottomLayerEndColor, bottomLayerDisabledEndColor); 
bottomEndColorAnimator.setDuration(animationDuration); 
bottomEndColorAnimator.setInterpolator(new LinearInterpolator()); 
bottomEndColorAnimator.addUpdateListener(animation -> { 
     shaderBottomLayerEndColor = (int) animation.getAnimatedValue(); 
     backLayerPaint.setShader(new LinearGradient(0, 0, 0, getHeight(), shaderBottomLayerStartColor, 
       shaderBottomLayerEndColor, Shader.TileMode.CLAMP)); 
    }); 

pointerColorAnimator = ValueAnimator.ofArgb(pointerEnabledColor, pointerDisabledColor); 
pointerColorAnimator.setDuration(animationDuration); 
pointerColorAnimator.setInterpolator(new LinearInterpolator()); 
pointerColorAnimator.addUpdateListener(animation -> { 
     pointerColor = (int) animation.getAnimatedValue(); 
     pointerPaint.setColor(pointerColor); 
    }); 

colorsAnimatorSet = new AnimatorSet(); 
colorsAnimatorSet.playTogether(frontStartColorAnimator, frontEndColorAnimator, 
      bottomStartColorAnimator, bottomEndColorAnimator, pointerColorAnimator); 

... 

colorsAnimatorSet.start(); 

También estaba preocupado al principio sobre la creación de un nuevo LinearGradient en cada actualización de la animación pero luego puse en marcha perfiles GPU en el dispositivo con "On pantalla como barras" . Todo está bien y funcionando dentro de un margen seguro.

Cuestiones relacionadas