Text color animation

前端 未结 8 1829
南旧
南旧 2020-12-14 10:09

Is there a way to animate a text color change (from anycolor to white)?

The only variant I came up with, is placing two textviews (with the same text) in one place,

相关标签:
8条回答
  • 2020-12-14 10:35

    The issue I found with valueAnimator as well as ObjectAnimator is that the animator iterates through a number of random colors, and the transition doesn't look smooth. I wrote the following code which worked smoothly. Hope it helps someone else also.

    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 讨论(0)
  • 2020-12-14 10:40

    The Easiest solution will be to use Object Animators :

    ObjectAnimator colorAnim = ObjectAnimator.ofInt(yourTextView, "textColor",
                Color.RED, Color.GREEN);
                colorAnim.setEvaluator(new ArgbEvaluator());
                colorAnim.start();
    
    0 讨论(0)
  • 2020-12-14 10:43

    As others mention, using ObjectAnimator solves for this. However, in the existing posts - I wasn't seeing how to set duration. For me the color change would happen immediately.

    The solution below shows:

    1. setting the animation with some interval; thanks to post: https://plus.google.com/+CyrilMottier/posts/X4yoNHHszwq

    2. a way to continuously cycle back and forth between the 2 colors


    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();
    }
    
    0 讨论(0)
  • 2020-12-14 10:44

    I scrapped the variant of the 2 TextViews since it looked weird (edges weren't smooth and, since I have a lot of such elements on the screen it was really lagging the scrolling). What I did, was a crazy hack that does the animation with the use of a Thread and setTextColor (that also forces redraw of a textview).

    Since I needed only 2 color changes (from red to white, and from green to white) I hardcoded the values and all of the transition colors between them. So here's how it looks:

    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;
        }
    }
    }
    
    0 讨论(0)
  • 2020-12-14 10:48

    Although I haven't found a totally distinct method, I have tried to use a TextSwitcher (with the fade animation) to create the colour-change effect. A TextSwitcher is a kind of ViewSwitcher which literally animates between two (internal) TextViews. Did you manually implement the same system unknowingly? ;) It manages a bit more of the process for you, so you may find it easier to work with (especially if you want to try more involved animations). I would create new subclass of TextSwitcher and some methods e.g. setColour() which can set the new colour and then trigger an animation. The animation code can then be moved outside of your main application.

    • make sure you keep a handle on the two TextViews that are put into the switcher
    • change the colour of the other TextView and call setText() to animate between them

    If you are already using a ViewSwitcher then I don't think there is an easier way to implement this.

    0 讨论(0)
  • 2020-12-14 10:48

    best way use ValueAnimator and 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();
    
    0 讨论(0)
提交回复
热议问题