Diese Frage ist fast in der Mitte des Jahres 2017 immer noch gültig. Ich wollte einen reibungslosen Übergang für Farbänderungen in meiner benutzerdefinierten Ansicht erstellen. Ich habe Shader mit LinearGradients verwendet.
Meine Absicht war es, einen reibungslosen Übergang zwischen dem aktivierten und deaktivierten Zustand meiner Ansicht zu schaffen.
Mein Fall ist aufgrund des Aufbaus und des Zwecks der Ansicht noch komplizierter. Es ist ein Schieberegler. Meine Ansicht besteht daher aus fast zwei identischen Ebenen, die mit Canvas übereinander gezeichnet sind. Das dritte Element ist ein Zeiger.
Beide Ebenen verwenden LinearGradients, der Zeiger verwendet eine einzige Farbe.
Zusammenfassend muss ich also gleichzeitig einen Übergang zwischen 5 Farben durchführen:
- Start- und Endfarbe für untere Ebene - ein LinearGradient,
- Start- und Endfarbe für obere Ebene - zweiter LinearGradient,
- Zeigerfarbe - normale Farbe;
Die Lösung dafür besteht darin, 5 separate ValueAnimators zu haben. Das Wichtigste ist, ValueAnimator.ofArgb() zu verwenden:
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();
Ich war zu Beginn auch besorgt darüber, bei jedem Animationsupdate einen neuen LinearGradient zu erstellen, aber dann habe ich das GPU-Profilieren auf dem Gerät mit "Auf dem Bildschirm als Balken" gestartet. Alles läuft gut und innerhalb eines sicheren Bereichs.