To pytanie jest nadal aktualne prawie w połowie 2017 roku. Chciałem stworzyć płynne przejście dla zmian kolorów dla mojego widoku niestandardowego. Użyłem shaderów z LinearGradients.
Moim zamiarem było sprawne przejście między stanem włączenia i wyłączenia mojego widoku.
Moja sprawa jest jeszcze bardziej skomplikowana ze względu na konstrukcję i cel widoku. To suwak. Tak więc mój widok składa się z prawie 2 identycznych warstw narysowanych jedna na drugiej za pomocą płótna. Trzecim elementem jest wskaźnik.
Obie warstwy używają LinearGradients, wskaźnik używa jednego koloru.
zsumowanie wszystkich trzeba wykonać przejście między 5 kolorów jednocześnie:
- start i barwą dla dolnej warstwy - jeden lineargradient,
- początkowy i końcowy kolor warstwy wierzchniej - druga lineargradient ,
- kolor wskaźnika - normalny kolor;
Rozwiązaniem tego problemu jest posiadanie 5 oddzielnych ValueAnimatorów. Najważniejszą rzeczą jest, aby używać 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();
Ja też na początku chodziło o stworzenie nowego lineargradient na każdej aktualizacji animacji ale potem rozpoczęła profilowanie GPU na urządzeniu z „Na ekranie barów” . Wszystko jest w porządku i działa w bezpiecznym marginesie.
Dzięki Romain, czy mógłbyś podzielić się z tobą swoją wiedzą na temat mojego komentarza do campingu? Zastanawiam się, jaka jest najbardziej efektywna metoda .draw ...(), to albo narysuj dwie warstwy wymagane do stworzenia tego efektu, albo jeśli LayerDrawable jest dokładnie tym, czego potrzebuję. – Greg
@Romain Guy Próbowałem użyć SweepGradient, aby uzyskać stożkowy efekt gradientu.Ale wydaje się, że działa tylko z dwoma kolorami. Jeśli używam tablicy czterech kolorów, ** SweepGradient ** nie działa zgodnie z oczekiwaniami. Próbowałem różnych kombinacji wartości ** position, a także próbowałem ustawień pozycji jako ** NULL **, ale większość otrzymuję tylko dwa kolory lub gradient, który nie jest stożkowy. Każda pomoc byłaby bardzo cenna. –