Сделать обновление ProgressBar плавно - PullRequest
51 голосов
/ 23 мая 2011

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

pb.setInterpolator(main.this, android.R.anim.bounce_interpolator);             
pb.setProgress(pb.getProgress()+10);

Я что-то не так делаю?

Ответы [ 6 ]

126 голосов
/ 14 апреля 2013

Интерполятор должен быть присоединен к анимации, и это будет работать только на сотах или выше:

if(android.os.Build.VERSION.SDK_INT >= 11){
    // will update the "progress" propriety of seekbar until it reaches progress
    ObjectAnimator animation = ObjectAnimator.ofInt(seekbar, "progress", progress); 
    animation.setDuration(500); // 0.5 second
    animation.setInterpolator(new DecelerateInterpolator());
    animation.start();
}
else 
    seekbar.setProgress(progress); // no animation on Gingerbread or lower

Если ваш минимальный SDK равен Gingerbread или ниже, добавьте

@TargetApi(Build.VERSION_CODES.HONEYCOMB) 
// or 
@SuppressLint("NewApi") 

к вашей функции / классу.

Я использовал DecelerateInterpolator, но это не обязательно, и есть другие возможности.

16 голосов
/ 22 декабря 2013

Вот автономное решение:

import android.animation.ValueAnimator;
import android.animation.ValueAnimator.AnimatorUpdateListener;
import android.content.Context;
import android.util.AttributeSet;
import android.view.animation.AccelerateDecelerateInterpolator;
import android.view.animation.Interpolator;
import android.widget.ProgressBar;

public class AnimatingProgressBar extends ProgressBar {

    private static final Interpolator DEFAULT_INTERPOLATER = new AccelerateDecelerateInterpolator();

    private ValueAnimator animator;
    private ValueAnimator animatorSecondary;
    private boolean animate = true;

    public AnimatingProgressBar(Context context, AttributeSet attrs, int defStyle) {
        super(context, attrs, defStyle);
    }

    public AnimatingProgressBar(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public AnimatingProgressBar(Context context) {
        super(context);
    }

    public boolean isAnimate() {
        return animate;
    }

    public void setAnimate(boolean animate) {
        this.animate = animate;
    }

    @Override
    public synchronized void setProgress(int progress) {
        if (!animate) {
            super.setProgress(progress);
            return;
        }
        if (animator != null)
            animator.cancel();
        if (animator == null) {
            animator = ValueAnimator.ofInt(getProgress(), progress);
            animator.setInterpolator(DEFAULT_INTERPOLATER);
            animator.addUpdateListener(new AnimatorUpdateListener() {

                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    AnimatingProgressBar.super.setProgress((Integer) animation.getAnimatedValue());
                }
            });
        } else
            animator.setIntValues(getProgress(), progress);
        animator.start();

    }

    @Override
    public synchronized void setSecondaryProgress(int secondaryProgress) {
        if (!animate) {
            super.setSecondaryProgress(secondaryProgress);
            return;
        }
        if (animatorSecondary != null)
            animatorSecondary.cancel();
        if (animatorSecondary == null) {
            animatorSecondary = ValueAnimator.ofInt(getProgress(), secondaryProgress);
            animatorSecondary.setInterpolator(DEFAULT_INTERPOLATER);
            animatorSecondary.addUpdateListener(new AnimatorUpdateListener() {

                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    AnimatingProgressBar.super.setSecondaryProgress((Integer) animation
                            .getAnimatedValue());
                }
            });
        } else
            animatorSecondary.setIntValues(getProgress(), secondaryProgress);
        animatorSecondary.start();
    }

    @Override
    protected void onDetachedFromWindow() {
        super.onDetachedFromWindow();
        if (animator != null)
            animator.cancel();
        if (animatorSecondary != null)
            animatorSecondary.cancel();
    }

}

замените ProgressBar на AnimatingProgressBar в вашем макете

Вы также можете изменить тип на AnimatingProgressBar для использования setAnimate() для отключения анимации (может быть полезно при восстановлении состояния активности)

12 голосов
/ 06 июля 2016

Если вы меняете значение прогресса каждый раз на 1 (например, с 45 на 46), вы не увидите анимацию.Лучше изменить прогресс на 100 баллов, для этого вам просто нужно умножить максимальное значение до 100 и каждое значение прогресса до 100.Например:

private void setProgressMax(ProgressBar pb, int max) {
    pb.setMax(max * 100);
}

private void setProgressAnimate(ProgressBar pb, int progressTo) 
{
    ObjectAnimator animation = ObjectAnimator.ofInt(pb, "progress", pb.getProgress(), progressTo * 100);
    animation.setDuration(500);
    animation.setInterpolator(new DecelerateInterpolator());
    animation.start();
}
3 голосов
/ 24 мая 2011

Я разобрался, как это сделать, с помощью запускаемого приложения я смог обновлять индикатор выполнения несколько раз в секунду и, таким образом, выдавать эффект скольжения.Код ниже:

private Runnable SmoothIncrement = new Runnable() {
       public void run() {
           final long start = mStartTime;
           long millis = SystemClock.uptimeMillis() - start;

           if(track!=increase) {
               if((pb.getProgress()==100)&&(count<target)) {
                   pb.setProgress(0);
               }
               pb.incrementProgressBy(1);
               track++;
               incrementor.postAtTime(this, start + millis);
           }
           else {
               incrementor.removeCallbacks(this);
           }
       }
    };

Здесь «track» отслеживает, сколько шагов было сделано, а увеличение - это общее количество шагов, которое должно быть сделано.Я могу динамически увеличивать количество приращений из потока пользовательского интерфейса, чтобы получить плавный эффект.Код работает только для индикаторов выполнения, которые не нужно уменьшать.

Чтобы запустить его, просто используйте этот код:

                    mStartTime = System.currentTimeMillis();
                    incrementor.removeCallbacks(SmoothIncrement);
                    if(track!=0) {
                        track -= increase;
                    }
                    incrementor.postDelayed(SmoothIncrement, 0);
1 голос
/ 23 мая 2011

Согласно документации, интерполятор применяется к неопределенному прогрессу. Поскольку вы устанавливаете прогресс, я думаю, что вы собираетесь использовать обычный со значениями. Я думаю, что лучшим для вас было бы увеличение максимальной ценности прогресса и идти в меньших приращениях.

1 голос
/ 23 мая 2011

Я не уверен, но, пожалуйста, проверьте это:

pb.setProgress(pb.getProgress() * 100);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...