在Android上自定义视图中模拟动画

Ali*_*lin 4 multithreading android android-custom-view android-animation

我有一个自定义视图,看起来像一个数字从0到9的旋转轮.基本上它从0向下滚动到我从服务器下载的东西,当返回值时,动画停止在它上面.通过更新我正在绘制的文本的Y值来制作动画

一些相关代码:

public class TimeSpinner extends View
{

    .....
    private void initialize()
    {
    .....

        handler = new Handler();
        repetitiveRunnable = new Runnable() {
            @Override
            public void run() {
                updateData();
            }
        };

    }

    public void updateData() {

        float delta = 3;

        mDigitY += delta;
        mDigitAboveY += delta;
        mDigitBelowY += delta;

        //Test if animation needs to stop
        if (mCurrentDigit == animateToDigit) {
            handler.removeCallbacks(repetitiveRunnable);
        } else {
            handler.postDelayed(repetitiveRunnable, 5);
        }

        invalidate();
    }


    public void startLoadingDigit() {
        handler.postDelayed(repetitiveRunnable, 5);
    }

    @Override
    protected void onDraw(Canvas canvas)
    {
        super.onDraw(canvas);

        canvas.drawText(mDigitString, mDigitX, mDigitY, mDigitPaint);
        canvas.drawText(mDigitAboveString, mDigitX, mDigitAboveY, mDigitPaint);
        canvas.drawText(mDigitBelowString, mDigitX, mDigitBelowY, mDigitPaint);

    }

}
Run Code Online (Sandbox Code Playgroud)

问题是UI线程在其他视图上有一些绘图要做,因此根据手机的速度,动画不流畅.就像有不良的帧率或有时它停止半秒.在强大的设备上是合理的好.

现在的问题是,我能做些什么使动画顺利地独立于应用程序的行为?视图很简单,而不是SurfaceView.我应该以某种方式使用线程吗?代码示例会很棒.

稍后编辑.

我尝试使用AsycTask来更新Y坐标

public class TimeSpinnerTask extends AsyncTask<Void, Void, Void> {

        @Override
        protected Void doInBackground(Void... arg0) {
            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);

            while (animationRunning) {

                updateData();
                publishProgress();

                try {
                    Thread.sleep(35);
                } catch (InterruptedException e) {

                }
            }
            return null;
        }


        @Override
        protected void onProgressUpdate(Void... values) {
            invalidate();
            super.onProgressUpdate(values);
        }

        @Override
        protected void onPostExecute(Void result) {
            invalidate();
            super.onPostExecute(result);
        }
    }

public void updateData() {

        mDigitY += delta;
        mDigitAboveY += delta;
        mDigitBelowY += delta;

        if (mDigitAboveY > findCenterY(mCurrentDigit)) {
            setCurrentDigit(mDigitAbove);
        }

        if (mCurrentDigit == animateToDigit) {

            animationRunning = false;

            setCurrentDigit(animateToDigit);
        }
    }
Run Code Online (Sandbox Code Playgroud)

虽然这似乎有点平滑,但在较旧的设备上我仍然可以获得快门,有时动画甚至暂停1秒后再继续.

asynctask开始于,executeOnExecutor并且视图显示在Android Maps V2的Map控件上.特别是当地图正在加载图块时,会出现模板.

也许我没有采用最好的方法.这是我想要获得的最终结果: 在此输入图像描述 有任何想法吗 ?

Kyl*_*vey 10

你试过用过ValueAnimator吗?这是专为管理与您的动画类似的动画而设计的.它将为您处理线程和帧率.

// Create a new value animator that will use the range 0 to 1
ValueAnimator animator = ValueAnimator.ofFloat(0, 1);

// It will take 5000ms for the animator to go from 0 to 1
animator.setDuration(5000);

// Callback that executes on animation steps. 
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value = ((Float) (animation.getAnimatedValue())).floatValue();

        Log.d("ValueAnimator", "value=" + value);

        // Here you can now translate or redraw your view
        // You need to map 'value' to your animation in regards to time
        // eg) mDigitY = value; invalidate();
    }
});
Run Code Online (Sandbox Code Playgroud)

您也可以使用动画在动画结束时达到弹性效果OvershootInterpolator.

animator.setInterpolator(new OvershootInterpolator());
Run Code Online (Sandbox Code Playgroud)