Search code examples
androidandroid-animationandroid-runonuithread

Android view doesn't update when trying to set values over time


I got a fragment which got a control called RingProgress which is simply a ring that fills itself according to a percentage value given. For example, if I do:

ringProgress.setProgress(20);

It means that 20% of the ring will now be filled.

What I'm trying to do is to animate the ring being filled over a few seconds. So what I've tried to do is this:

@Override
public void onResume()
{
    super.onResume();
    HandlerThread handlerThread = new HandlerThread("countdown");
    handlerThread.start();
    Handler handler = new Handler(handlerThread.getLooper());
    handler.post(new Runnable()
    {
        @Override
        public void run()
        {
            final Timer timer = new Timer();
            timer.scheduleAtFixedRate(new TimerTask()
            {
                int totalSeconds = secondsToStart + minutesToStart * 60;
                int secondsPassed = 0;

                @Override
                public void run()
                {
                    if(secondsPassed == totalSeconds)
                    {
                        timer.cancel();
                    }
                    final int currentProgress = (secondsPassed / totalSeconds) * 100;
                    secondsPassed++;
                    getActivity().runOnUiThread(new Runnable()
                    {
                        @Override
                        public void run()
                        {
                            mRingProgressBar.setProgress(currentProgress);
                        }
                    });

                }
            }, 0, 1000);

        }
    });
}

The problem is that the update of the ring is not shown until the time is up. For example, if I set it for 5 seconds then when the fragment loads the ring is set to 0, then nothing happens for 5 seconds and then the ring is full with 100% all at once..

How can I start this animation properly?


Solution

  • Instead of using a handler, you could use a property animator as follows:

    ObjectAnimator.ofInt(mRingProgressBar, "progress", 0, 100)
        .setDuration(totalSeconds * 1000)   //time is in miliseconds
        .start();
    

    This will find a method setProgress() in your mRingProgressBarand set the value according to the limits given. In the example above, 0 to 100. You can read more about it here