2011-01-11 5 views
11

Есть ли способ анимировать изменение цвета текста (от любого цвета до белого)?Текстовая анимация цвета

Единственный вариант, который я придумал, размещает два текстовых изображения (с одним и тем же текстом) в одном месте и затухает сверху, поэтому нижний (имеющий белый цвет) станет видимым.

P.S. Я отказался от варианта 2 TextViews, так как он выглядел странно (края были негладкими, и, поскольку на экране было много таких элементов, это действительно задерживало прокрутку). То, что я сделал, было безумным взломом, который делает анимацию с использованием Thread и setTextColor (что также заставляет перерисовывать текстовое представление).

Поскольку мне нужно было всего 2 изменения цвета (от красного до белого и от зеленого до белого), я жестко закодировал значения и все цвета перехода между ними. Так вот как это выглядит:

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; 
    } 
} 
} 

ответ

3

Хотя я не нашел совершенно отличный способ, я попытался использовать TextSwitcher (с выцветанию анимацией), чтобы создать эффект изменения цвета. A TextSwitcher - это вид ViewSwitcher, который буквально оживляет между двумя (внутренними) TextView с. Вы вручную использовали ту же систему бессознательно? ;) Он управляет немного больше процесса для вас, поэтому вам будет легче работать (особенно если вы хотите попробовать более привлекательные анимации). Я бы создал новый подкласс TextSwitcher и некоторые методы, например. setColour(), который может установить новый цвет, а затем вызвать анимацию. Затем код анимации можно перемещать за пределы основного приложения.

  • убедитесь, что вы держите ручку на двух TextView с, которые ставятся в переключателе
  • изменить цвет другой TextView и вызвать setText() анимировать между ними

Если вы уже используя ViewSwitcher, тогда я не думаю, что есть более простой способ реализовать это.

+0

Спасибо , Я фактически не реализовал метод, о котором я говорил (просто подумал об этом). Спасибо большое, я попробую ваш метод сейчас :) –

3

Не нужно оставлять ручки для двух текстовых просмотров. Сначала добавьте анимацию FadeIn/Затухание:

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

затем:

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); 

Просто реализовали его, как это так, доказала свою работу.

0

Я отказался от варианта 2 TextViews, так как он выглядел странно (края были негладкими, и, поскольку на экране было много таких элементов, это действительно задерживало прокрутку). То, что я сделал, было безумным взломом, который делает анимацию с использованием Thread и setTextColor (что также заставляет перерисовывать текстовое представление).

Поскольку мне нужно было всего 2 изменения цвета (от красного до белого и от зеленого до белого), я жестко закодировал значения и все цвета перехода между ними. Так вот как это выглядит:

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

Вы можете использовать новый Property Animation Api для цветной анимации:

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(); 

Для обратной совместимости с использованием Android 2.x Nine Old Androids library от Jake Wharton.

17

Самым простым решением будет использовать аниматоры Объект:

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

это лучший ответ, спасибо –

+0

как контролировать скорость объектного элементатора? – pollaris

0

Проблема, которую я нашел с valueAnimator, а также ObjectAnimator является то, что аниматор перебирает ряд случайных цветов, и переход не выглядит гладкий; плавный. Я написал следующий код, который работал гладко. Надеюсь, это поможет и другому.

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

Как упоминалось, использование ObjectAnimator решает для этого. Однако в существующих сообщениях я не видел, как установить продолжительность. Для меня изменение цвета произойдет немедленно.

Раствор ниже показано:

  1. установки анимации с некоторым интервалом; благодаря должность: https://plus.google.com/+CyrilMottier/posts/X4yoNHHszwq

  2. способ непрерывного цикла назад и вперед между 2-х цветов


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

лучший способ использовать ValueAnimator и 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(); 
Смежные вопросы