RedBounce
RedBounce

Reputation: 213

How to set smoothly animation to progressBar in android

In my project I want use ProgressBar and I want set smoothly countdown animation.

I write below codes for smoothly animation and when set 1000ms (1s) for duration show smoothly animation, but I want set 10000ms (10s) for duration.

When set 10000ms (10s) for duration not smoothly animation and show Fragmentary countdown.

But I want set 10000ms for duration and show smoothly countdown.

public class SimpleFrag extends Fragment {

    TextView toolbar_title;
    RelativeLayout toolbar;
    private ProgressBar progressBar;

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View view = inflater.inflate(R.layout.fragment_simple, container, false);

        ButterKnife.bind(this, view);
        toolbar_title = getActivity().findViewById(R.id.toolbar_title);
        toolbar = getActivity().findViewById(R.id.toolbar);
        progressBar = view.findViewById(R.id.progress);

        return view;
    }

    @Override
    public void setUserVisibleHint(boolean isVisibleToUser) {
        super.setUserVisibleHint(isVisibleToUser);
        if (isVisibleToUser) {
            final Handler handler = new Handler();
            handler.postDelayed(new Runnable() {
                @SuppressLint("ObjectAnimatorBinding")
                @Override
                public void run() {
                    ProgressBarAnimation mProgressAnimation = new ProgressBarAnimation(progressBar, 79, 0);
                    mProgressAnimation.setDuration(10000);
                    progressBar.startAnimation(mProgressAnimation);
                }
            }, 50);
        }
    }

    public class ProgressBarAnimation extends Animation {
        private ProgressBar progressBar;
        private float from;
        private float to;

        public ProgressBarAnimation(ProgressBar progressBar, float from, float to) {
            super();
            this.progressBar = progressBar;
            this.from = from;
            this.to = to;
        }

        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            super.applyTransformation(interpolatedTime, t);
            float value = from + (to - from) * interpolatedTime;
            progressBar.setProgress((int) value);
        }
    }
}

How can I it? please help me . Thanks all <3

Upvotes: 2

Views: 7523

Answers (1)

Ben P.
Ben P.

Reputation: 54204

Take what you have now, and delete your setUserVisibleHint() method and your ProgressBarAnimation class. Add this:

private void setUpObserver() {
    progressBar.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
        @Override
        public void onGlobalLayout() {
            startAnimation();

            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
                progressBar.getViewTreeObserver().removeOnGlobalLayoutListener(this);
            }
            else {
                progressBar.getViewTreeObserver().removeGlobalOnLayoutListener(this);
            }
        }
    });
}

private void startAnimation() {
    int width = progressBar.getWidth();
    progressBar.setMax(width);

    ValueAnimator animator = ValueAnimator.ofInt(0, width);
    animator.setInterpolator(new LinearInterpolator());
    animator.setStartDelay(0);
    animator.setDuration(10_000);
    animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator valueAnimator) {
            int value = (int) valueAnimator.getAnimatedValue();
            progressBar.setProgress(value);
        }
    });

    animator.start();
}

Then, inside your onCreateView() method, call setUpObserver() right before you return view;

The setUpObserver() method uses an OnGlobalLayoutListener to make sure that the system waits until the ProgressBar is measured an laid out before starting the animation.

The startAnimation() method is what takes care of actually setting up and running the animation. You can modify the values passed to setStartDelay() and setDuration() as you see fit.

The trick to this solution is making sure that the maximum value for the progress bar is equal to its width, meaning that each increment of "progress" is equal to one pixel on the screen. The android framework animation takes care of making sure everything runs as smoothly as possible.

Edit

If you want to be able to control the start/end points for the animation (rather than just go from empty to full), make these changes:

Change the declaration of startAnimation() to this:

private void startAnimation(float startPercent, float endPercent)

Delete this line from inside startAnimation()

ValueAnimator animator = ValueAnimator.ofInt(0, width);

and add these lines instead:

int start = (int) (startPercent * width);
int end = (int) (endPercent * width);
ValueAnimator animator = ValueAnimator.ofInt(start, end);

Finally, call startAnimation() by passing in fractional percentages:

startAnimation(0.79f, 0.10f); // will animate from 79% to 10%

Upvotes: 10

Related Questions