平滑的进度条动画

37

我正在尝试为我的ProgressBar实现平滑动画,但当我增加时间(30秒)时,动画就不再流畅。

5秒的示例:

5 seconds

30秒的示例:

30 seconds

我的进度条背景:

<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
    <item>
        <shape>
            <padding android:top="1dp" />
            <solid android:color="#10444444" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" />
            <solid android:color="#20444444" />
        </shape>
    </item>
    <item>
        <shape>
            <padding android:top="1dp" />
            <solid android:color="#30444444" />
        </shape>
    </item>
    <item android:id="@android:id/background">
        <shape>
            <solid android:color="@color/black_thirty" />
        </shape>
    </item>

    <item android:id="@android:id/progress">
        <clip>
            <shape>
                <solid android:color="#3500D0" />
            </shape>
        </clip>
    </item>
</layer-list> 

我的进展布局:

<ProgressBar
    android:id="@+id/pb_loading"
    android:layout_width="match_parent"
    android:layout_height="8dp"
    android:indeterminate="false"
    android:layout_centerInParent="true"
    android:progress="100"
    android:progressDrawable="@drawable/my_progress_bar" />

我的动画方法:

private void startAnimation(){
    ProgressBar mProgressBar = (ProgressBar) findViewById(R.id.pb_loading);
    ObjectAnimator progressAnimator = ObjectAnimator.ofInt(mProgressBar, "progress", 100, 0);
    progressAnimator.setDuration(30000);
    progressAnimator.setInterpolator(new LinearInterpolator());
    progressAnimator.start();
}

请查看此链接 https://stackoverflow.com/a/48599412/7212498 - Rahul
10个回答

47

如果每次将进度值增加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.setAutoCancel( true);
        animation.setInterpolator( new DecelerateInterpolator());
        animation.start();
    }

谢谢!它确实有帮助。 - Kruti Parekh
这个是可以工作的。但是由于每次进度变化时都需要进行乘法运算,会对性能产生影响吗? - Chaitanya Karmarkar
@ChaitanyaKarmarkar 是的,很可能会,因为它将比以前更经常地改变一个非常小的量。不过这也取决于你将其乘以多少。 - Sujit

30
因为你正在使用ofInt,所以你只能以完整的整数移动。换句话说,如果你有一个宽度为1000的进度条和一个进度从0到100的进度,由于你是以整数步长移动,你会计数1、2、3、4,这相当于10像素、20像素、30像素和40像素。这解释了你所看到的锯齿状。
要纠正这个问题,你有几个选择。第一个是将你的整数从0增加到someBigInt。这将为动画师提供更多的数字来处理。
ObjectAnimator progressAnimator = ObjectAnimator.ofInt(mProgressBar, "progress", 10000, 0);
另一个选项是使用ofFloat,它与ofInt具有相同的功能,但使用浮点数而不是整数。
ObjectAnimator progressAnimator = ObjectAnimator.ofFloat(mProgressBar, "progress", 100.0, 0.0);

3
我试过了!但是,当我改成 ObjectAnimator.ofFloat(mProgressBar, "progress", 100.0f, 0.0f); 后,动画没有开始。 - rsicarelli
哦,那么可能还有其他问题...尝试在 progressAnimator.start(); 之后调用 mProgressBar.invalidate(); - Chris Stillwell
5
无法工作,因为progressBar.setProgress(int)方法需要传入整数而非浮点数! - maXp

20

9

XML

       <ProgressBar
        android:id="@+id/progress_bar"
        style="@style/Widget.AppCompat.ProgressBar.Horizontal"
        android:layout_width="match_parent"
        android:layout_height="4dp"
        android:indeterminate="false"
        android:progress="0"
        android:max="100"/>

JAVA

@BindView(R.id.progress_bar) ProgressBar progressBar;
ObjectAnimator.ofInt(progressBar, "progress", 79).start();

79

  • 此示例中的任何数字介于0和100之间

9

只需设置 android:max="1000" 并执行 ObjectAnimator progressAnimator = ObjectAnimator.ofInt(mProgressBar, "progress", 1000, 0);

在这种情况下,每次步进的动画将是总进度的1/1000,在默认100%比例下平滑进行10次。看起来更加流畅和美观。


请始终添加说明,说明如何以及为什么这会有所帮助。 - David Medenjak

3

由于ProgressBar的进度属性只接受整数值,而不接受浮点值,因此您不能使用ofFloat。这就是为什么在使用该解决方案后,您的ProgressBar停止了进展。

正如其他人所说,实现您想要的正确方法是将android:max设置为一个大整数。

抱歉重新激活线程,但我觉得这必须被说出来。


1

Android N 提供了一个变体 setProgress(newProgress, true),支持动画进度。

虽然需要进行版本检查,但是还有另一种方法可以直接使用 setProgressCompat(progress, true),无论版本如何。

progressBar.setProgressCompat(progress, true)

1
你可以像这样创建自定义类:

public class CustomProgressBar extends ProgressBar {
private static final long DEFAULT_DELAY = 500;
private static final long DEFAULT_DURATION = 1000;

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

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

public CustomProgressBar(Context context, AttributeSet attrs, int defStyleAttr) {
    super(context, attrs, defStyleAttr);
}

public synchronized void setProgress(float progress) {
    super.setProgress((int) progress);
}

@Override
public synchronized void setProgress(int progress) {
    super.setProgress(progress);
}

public void startLcpProgressAnim(int progressTo) {
   startLcpProgressAnim(DEFAULT_DELAY, progressTo);
}

public void startLcpProgressAnim(long delay, int progressTo) {
   startLcpProgressAnim(DEFAULT_DURATION, delay, progressTo);
}

public void startLcpProgressAnim(long duration, long delay, float progressTo) {
    ObjectAnimator animation = ObjectAnimator.
            ofFloat(this, "progress",
                    (float)this.getProgress(), progressTo);
    animation.setDuration(duration);
    animation.setStartDelay(delay);
    animation.start();
}
}

1

以下是我使用平滑动画编写的倒计时器代码片段,您可以根据需要进行修改,请按照以下步骤操作:

private void setProgressBarValues() {
        progressBarCircle.setMax((int) (timeCountInMilliSeconds / 10));
        progressBarCircle.setProgress((int) (timeCountInMilliSeconds / 10));
        Log.e("progres", "" + (timeCountInMilliSeconds / 10));
    }

private void startCountDownTimer() {

        smoothAnimation = ObjectAnimator.ofInt(progressBarCircle, "progress", progressBarCircle.getProgress(), progressBarCircle.getMax());
        smoothAnimation.setDuration(500);
        smoothAnimation.setInterpolator(new AccelerateInterpolator());

        countDownTimer = new CountDownTimer(timeCountInMilliSeconds, 10) {
            @Override
            public void onTick(long millisUntilFinished) {

                Log.e("getMax", "" + progressBarCircle.getMax());
                Log.e("getprogres", "" + progressBarCircle.getProgress());
                textViewTime.setText(hmsTimeFormatter(millisUntilFinished));
                progressBarCircle.setProgress((int) (timeCountInMilliSeconds / 10 - millisUntilFinished / 10));
            }

            @Override
            public void onFinish() {

                textViewTime.setText(hmsTimeFormatter(timeCountInMilliSeconds));
                // call to initialize the progress bar values
                setProgressBarValues();
                // hiding the reset icon
                buttonReset.setEnabled(false);
                // making edit text editable
                editTextMinute.setEnabled(true);
                // changing the timer status to stopped
                status = TimerStatus.STOPPED;
                smoothAnimation.end();
            }

        }.start();
        smoothAnimation.start();
        countDownTimer.start();
    }

摘要:

  1. setMax和setProgress

  2. 设置动画以显示进度条的进度值从当前值到最大值

  3. 创建一个定时器,回调时间为约10毫秒

  4. 在onTick中更新进度,即总数-已完成数


1

使用该库可以帮助您在所需时间内填充进度条,其非常流畅无卡顿,但您需要进行一些自定义才能使用它。

只需将依赖项添加到您的build.gradle中:

compile 'com.carlosmuvi.segmentedprogressbar:library:0.2'

接下来,将其添加到您的布局中。
  <com.carlosmuvi.segmentedprogressbar.SegmentedProgressBar
      android:id="@+id/segmented_progressbar"
      android:layout_width="match_parent"
      android:layout_height="5dp"/>

最后,通过编程进行个性化定制并播放!
segmentedProgressBar = (SegmentedProgressBar) findViewById(R.id.segmented_progressbar);

// number of segments in your bar
segmentedProgressBar.setSegmentCount(7); 

//empty segment color
segmentedProgressBar.setContainerColor(Color.BLUE); 
//fill segment color
segmentedProgressBar.setFillColor(Color.GREEN); 

//play next segment specifying its duration
segmentedProgressBar.playSegment(5000);

//pause segment
segmentedProgressBar.pause();

//set filled segments directly
segmentedProgressBar.setCompletedSegments(3);

前往图书馆


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接