0

我得到了一个片段,它有一个名为的控件RingProgress,它只是一个根据给定百分比值填充自身的环。例如,如果我这样做:

ringProgress.setProgress(20);

这意味着现在将填充 20% 的环。

我正在尝试做的是在几秒钟内为填充的环设置动画。所以我试图做的是:

@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);

        }
    });
}

问题是直到时间到了才显示环的更新。例如,如果我将其设置为 5 秒,那么当片段加载时,环设置为 0,然后 5 秒内没有任何反应,然后环立即充满 100%。

如何正确启动此动画?

4

4 回答 4

3

我想问题出在

final int currentProgress = (secondsPassed / totalSeconds) * 100;

secondsPassed / totalSeconds返回 int 值,因此它将仅为 0 或 1。然后你将它乘以 100。

您必须使用floatordouble代替

就像是

final int currentProgress = Math.round(((float) secondsPassed)/((float) totalSeconds)*100f);
于 2017-03-02T08:59:28.030 回答
2

在这条线上:

Handler handler = new Handler(handlerThread.getLooper());

您正试图从handlerThread. 但是你怎么确定looper已经被初始化了?

从文档getLooper()

此方法返回与此线程关联的 Looper。如果这个线程没有被启动或者由于任何原因 isAlive() 返回 false,这个方法将返回 null。如果这个线程已经启动,这个方法会一直阻塞直到looper被初始化。

onLooperPrepared()是回调,您可以确定Looper已经初始化,因此您可以在其上构造逻辑。

因此,您要做的就是从回调子类化HandlerThread并创建适当的逻辑。onLooperPrepared()

这是一个很好的帖子,可以帮助你。见MyWorkerThread那里类的实现。

于 2017-03-02T09:02:03.810 回答
1

您可以使用属性动画器,而不是使用处理程序,如下所示:

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

这将setProgress()在您的方法中找到一个方法,mRingProgressBar并根据给定的限制设置值。在上面的示例中,0 到 100。您可以在此处阅读有关它的更多信息

于 2017-03-02T09:01:23.867 回答
0

由于你想在不同的线程上运行,你可以在类的顶部使用这个处理程序:

     private int progress = 0;
     Handler timerHandler = new Handler();
     Runnable timerRunnable = new Runnable() {
            @Override
            public void run() {

            ringProgress.setProgress(progress);
            progress += 20;
            if (progress == 100) { //clear??
            }
            timerHandler.postDelayed(this, 1000);
        }
    };

inCreate设置最大值:

ringProgress.setMax(100);

这将在 5 秒内完成动画,然后您可以清除动画。如果您想要更小的增量,请更改下面的行(每十分之一秒更新一次),并更改步骤

timerHandler.postDelayed(this, 100);
于 2017-03-02T09:16:38.627 回答