2011-01-11 12 views
11

Czy istnieje sposób na animację zmiany koloru tekstu (z anycolor na biały)?Animacja kolorów tekstu

Jedynym wariantem, jaki wymyśliłem, jest umieszczenie dwóch odsłon tekstu (z tym samym tekstem) w jednym miejscu i zanikających górnych, aby dolny (który ma biały kolor) stał się widoczny.

P.S. Zniszczyłem wariant 2 TextViewów, ponieważ wyglądało to dziwnie (krawędzie nie były gładkie, a ponieważ mam dużo takich elementów na ekranie, to naprawdę opóźniałem przewijanie). To, co zrobiłem, to szalony hack, który wykonuje animację za pomocą wątku i setTextColor (który również wymusza odrysowanie tekstu).

Ponieważ potrzebowałem tylko 2 zmiany koloru (z czerwonego na biały iz zielonego na biały), zakodowałem na stałe wartości i wszystkie kolory przejścia między nimi. Więc oto jak to wygląda:

public class BlinkingTextView extends TextView { 
public BlinkingTextView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

public void animateBlink(final boolean red) { 
    if (animator != null) { 
     animator.drop(); 
    } 
    animator = new Animator(this, red); 
    animator.start(); 
} 

public void clearBlinkAnimation() { 
    if (animator != null) { 
     animator.drop(); 
    } 
} 

private Animator animator; 

private final static class Animator extends Thread { 
    public Animator(final TextView textView, final boolean red) { 
     this.textView = textView; 
     if (red) { 
      SET_TO_USE = RED; 
     } else { 
      SET_TO_USE = GREEN; 
     } 
    } 

    private TextView textView; 

    private final int[] SET_TO_USE; 

    private final static int[] RED = { 
     -2142396, 
     -2008754, 
     -1874854, 
     -1740697, 
     -1540490, 
     -1405563, 
     -1205099, 
     -1004634, 
     -804170, 
     -669243, 
     -469036, 
     -334879, 
     -200979, 
     -67337, 
     -1 
    }; 
    private final static int[] GREEN = { 
     -6959821, 
     -6565826, 
     -6106293, 
     -5646758, 
     -5055894, 
     -4530309, 
     -3939444, 
     -3283042, 
     -2692177, 
     -2166592, 
     -1575728, 
     -1116193, 
     -656660, 
     -262665, 
     -1 
    }; 

    private boolean stop; 

    @Override 
    public void run() { 
     int i = 0; 
     while (i < 15) { 
      if (stop) break; 
      final int color = SET_TO_USE[i]; 
      if (stop) break; 
      textView.post(new Runnable() { 
       @Override 
       public void run() { 
        if (!stop) { 
         textView.setTextColor(color);      
        } 
       } 
      }); 
      if (stop) break; 
      i++; 
      if (stop) break; 
      try { 
       Thread.sleep(66); 
      } catch (InterruptedException e) {} 
      if (stop) break; 
     } 
    } 

    public void drop() { 
     stop = true; 
    } 
} 
} 

Odpowiedz

3

Chociaż nie znaleźli całkowicie odrębną metodę, próbowałem użyć TextSwitcher (z animacji na blaknięcie), aby stworzyć efekt zmiany kolorów. A TextSwitcher jest rodzajem ViewSwitcher, który dosłownie animuje pomiędzy dwoma (wewnętrznymi) TextView s. Czy ręcznie wprowadziłeś ten sam system nieświadomie? ;) Zarządza on nieco więcej procesem dla ciebie, możesz więc łatwiej pracować (zwłaszcza, jeśli chcesz spróbować bardziej zaangażowanych animacji). Chciałbym stworzyć nową podklasę TextSwitcher i niektóre metody, np. setColour(), który może ustawić nowy kolor, a następnie uruchomić animację. Kod animacji można następnie przenieść poza główną aplikację.

  • upewnij się zachować uchwyt na dwóch TextView s, które są wprowadzone do przełącznika
  • zmienić kolor z drugiej TextView i nazywają setText() animować między nimi

Jeśli już są używając ViewSwitcher, nie wydaje mi się, że istnieje łatwiejszy sposób wdrożenia tego.

+0

Dzięki . Właściwie nie zaimplementowałem metody, o której mówiłem (tylko o tym pomyślałem). Wielkie dzięki, wypróbuję teraz Twoją metodę :) –

3

Nie trzeba przechowywać uchwytów w dwóch widokach tekstu. Najpierw dodać animacje fadeIn/Fadeout:

textSwitcher.setInAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_in)); 
textSwitcher.setOutAnimation(AnimationUtils.loadAnimation(this, android.R.anim.fade_out)); 

następnie:

TextView currentTextView = (TextView)(textSwitcher.getNextView().equals(
    textSwitcher.getChildAt(0)) ? 
    textSwitcher.getChildAt(1) : textSwitcher.getChildAt(0) 
); 
// setCurrentText() first to be the same as newText if you need to 
textSwitcher.setTextColor(fadeOutColor); 
((TextView) textSwitcher.getNextView()).setTextColor(Color.WHITE); 
textSwitcher.setText(newText); 

Właśnie tak to realizowane tak okazały się skuteczne.

0

Złomowałem wariant 2 widoków tekstowych, ponieważ wyglądały dziwnie (krawędzie nie były gładkie, a ponieważ mam dużo takich elementów na ekranie, to naprawdę opóźniałem przewijanie). To, co zrobiłem, to szalony hack, który wykonuje animację za pomocą wątku i setTextColor (który również wymusza odrysowanie tekstu).

Ponieważ potrzebowałem tylko 2 zmiany koloru (z czerwonego na biały iz zielonego na biały), zakodowałem na stałe wartości i wszystkie kolory przejścia między nimi. Więc oto jak to wygląda:

public class BlinkingTextView extends TextView { 
public BlinkingTextView(Context context, AttributeSet attrs) { 
    super(context, attrs); 
} 

public void animateBlink(final boolean red) { 
    if (animator != null) { 
     animator.drop(); 
    } 
    animator = new Animator(this, red); 
    animator.start(); 
} 

public void clearBlinkAnimation() { 
    if (animator != null) { 
     animator.drop(); 
    } 
} 

private Animator animator; 

private final static class Animator extends Thread { 
    public Animator(final TextView textView, final boolean red) { 
     this.textView = textView; 
     if (red) { 
      SET_TO_USE = RED; 
     } else { 
      SET_TO_USE = GREEN; 
     } 
    } 

    private TextView textView; 

    private final int[] SET_TO_USE; 

    private final static int[] RED = { 
     -2142396, 
     -2008754, 
     -1874854, 
     -1740697, 
     -1540490, 
     -1405563, 
     -1205099, 
     -1004634, 
     -804170, 
     -669243, 
     -469036, 
     -334879, 
     -200979, 
     -67337, 
     -1 
    }; 
    private final static int[] GREEN = { 
     -6959821, 
     -6565826, 
     -6106293, 
     -5646758, 
     -5055894, 
     -4530309, 
     -3939444, 
     -3283042, 
     -2692177, 
     -2166592, 
     -1575728, 
     -1116193, 
     -656660, 
     -262665, 
     -1 
    }; 

    private boolean stop; 

    @Override 
    public void run() { 
     int i = 0; 
     while (i < 15) { 
      if (stop) break; 
      final int color = SET_TO_USE[i]; 
      if (stop) break; 
      textView.post(new Runnable() { 
       @Override 
       public void run() { 
        if (!stop) { 
         textView.setTextColor(color);      
        } 
       } 
      }); 
      if (stop) break; 
      i++; 
      if (stop) break; 
      try { 
       Thread.sleep(66); 
      } catch (InterruptedException e) {} 
      if (stop) break; 
     } 
    } 

    public void drop() { 
     stop = true; 
    } 
} 
} 
41

można wykorzystywać nowy Property Animation Api animacji koloru:

Integer colorFrom = getResources().getColor(R.color.red); 
Integer colorTo = getResources().getColor(R.color.blue); 
ValueAnimator colorAnimation = ValueAnimator.ofObject(new ArgbEvaluator(), colorFrom, colorTo); 
colorAnimation.addUpdateListener(new AnimatorUpdateListener() { 

    @Override 
    public void onAnimationUpdate(ValueAnimator animator) { 
     textView.setTextColor((Integer)animator.getAnimatedValue()); 
    } 

}); 
colorAnimation.start(); 

wstecznej kompatybilności Do użytku z Android 2.x Nine Old Androids library z Jake Wharton.

17

najprostszym rozwiązaniem będzie użycie animatorzy obiektu:

ObjectAnimator colorAnim = ObjectAnimator.ofInt(yourTextView, "textColor", 
      Color.RED, Color.Green); 
      colorAnim.setEvaluator(new ArgbEvaluator()); 
      colorAnim.start(); 
+0

to jest najlepsza odpowiedź, dziękuję –

+0

jak kontrolować prędkość obiektu? – pollaris

0

Wydanie I z valueAnimator znaleźć jak ObjectAnimator jest to, że iteracje animator poprzez szereg losowych kolorów i przejścia nie wygląda gładki. Napisałem poniższy kod, który działał sprawnie. Mam nadzieję, że pomoże to komuś innemu.

public static void changeTextColor(final TextView textView, int startColor, int endColor, 
            final long animDuration, final long animUnit){ 
    if (textView == null) return; 

    final int startRed = Color.red(startColor); 
    final int startBlue = Color.blue(startColor); 
    final int startGreen = Color.green(startColor); 

    final int endRed = Color.red(endColor); 
    final int endBlue = Color.blue(endColor); 
    final int endGreen = Color.green(endColor); 

    new CountDownTimer(animDuration, animUnit){ 
     //animDuration is the time in ms over which to run the animation 
     //animUnit is the time unit in ms, update color after each animUnit 

     @Override 
     public void onTick(long l) { 
      int red = (int) (endRed + (l * (startRed - endRed)/animDuration)); 
      int blue = (int) (endBlue + (l * (startBlue - endBlue)/animDuration)); 
      int green = (int) (endGreen + (l * (startGreen - endGreen)/animDuration)); 

      textView.setTextColor(Color.rgb(red, green, blue)); 
     } 

     @Override 
     public void onFinish() { 
      textView.setTextColor(Color.rgb(endRed, endGreen, endBlue)); 
     } 
    }.start(); 
} 
0

Jak wspominają inni, zastosowanie do tego rozwiązuje się za pomocą ObjectAnimator. Jednak w istniejących postach - nie widziałem, jak ustawić czas trwania. Dla mnie zmiana koloru nastąpiłaby natychmiast.

roztworu poniżej pokazuje:

  1. ustawienie animację z pewnego przedziału; Dzięki pisać: https://plus.google.com/+CyrilMottier/posts/X4yoNHHszwq

  2. sposób ciągły cykl iz powrotem między 2 kolorach


void animateTextViewColors(TextView textView, Integer colorTo) { 

    final Property<TextView, Integer> property = new Property<TextView, Integer>(int.class, "textColor") { 
     @Override 
     public Integer get(TextView object) { 
      return object.getCurrentTextColor(); 
     } 

     @Override 
     public void set(TextView object, Integer value) { 
      object.setTextColor(value); 
     } 
    }; 

    final ObjectAnimator animator = ObjectAnimator.ofInt(textView, property, colorTo); 
    animator.setDuration(8533L); 
    animator.setEvaluator(new ArgbEvaluator()); 
    animator.setInterpolator(new DecelerateInterpolator(2)); 
    animator.start(); 
} 

void oscillateDemo(final TextView textView) { 

    final int whiteColor = ContextCompat.getColor(TheApp.getAppContext(), R.color.white); 
    final int yellowColor = ContextCompat.getColor(TheApp.getAppContext(), R.color.yellow); 

    final int counter = 100; 

    Thread oscillateThread = new Thread() { 
     @Override 
     public void run() { 

      for (int i = 0; i < counter; i++) { 

       final int fadeToColor = (i % 2 == 0) 
         ? yellowColor 
         : whiteColor; 

       getActivity().runOnUiThread(new Runnable() { 
        @Override 
        public void run() { 

         animateTextViewColors(textView, fadeToColor); 
        } 
       });          

       try { 
        Thread.sleep(2450); 
       } 
       catch (InterruptedException iEx) {} 
      } 
     } 
    }; 

    oscillateThread.start(); 
} 
1

najlepszy sposób wykorzystywać ValueAnimator i ColorUtils.blendARGB

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f); 
valueAnimator.setDuration(325); 
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { 
     @Override 
     public void onAnimationUpdate(ValueAnimator valueAnimator) { 

       float fractionAnim = (float) valueAnimator.getAnimatedValue(); 

       textView.setTextColor(ColorUtils.blendARGB(Color.parseColor("#FFFFFF") 
            , Color.parseColor("#000000") 
            , fractionAnim)); 
     } 
}); 
valueAnimator.start();