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.
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
@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. –