Android:onDraw不断调用或动画捕捉到原始位置

时间:2012-01-15 15:41:02

标签: android android-animation android-view

所以,我的问题有点类似于这两个问题:

Custom View onDraw is constantly called

android: onDraw is called constantly

我有一个扩展ImageView的自定义类,我将RotateAnimation应用于。动画使用输入x和y坐标执行从最后一个角度到下一个角度的旋转,以便用户可以根据需要将ImageView从-360度旋转到360度。当我将这个代码用于onDraw()时,屏幕上的一切看起来都很完美(动画设置如下面的代码所示):

@Override
protected void onDraw(Canvas canvas) {
    Log.d(TAG, "It is drawn again!");
    this.setAnimation(anim);
    super.onDraw(canvas);
}

问题在于,与上述其他帖子一样,动画调用onDraw调用动画等,可能是通过RotateAnimation类中的invalidate()。这是否正确观察到了?输出是完美的,因为ImageView始终保持当前计算的角度,但动画计算因此继续进行,消耗大量的功率和容量。

为了解决这个问题,我尝试在计算动画参数的方法中移动this.setAnimation(anim)(请忽略isClockWise(),calculateAngleToMove()和其他非Android内容,它们按预期工作) :

private void turnWheel(){
    float angle = 0;

    if ( isClockWise() ){
        angle = calculateAngleToMove();         
        anim = new RotateAnimation(current_angle, angle, center_x, center_y);
        anim.setFillAfter(true);
        anim.setFillEnabled(true);
        current_angle += angle; 
    }
    else{
        angle = - calculateAngleToMove();
        anim = new RotateAnimation(current_angle, angle, center_x, center_y);
        anim.setFillAfter(true);
        anim.setFillEnabled(true);
        current_angle += angle;
    }

    if ( current_angle > 360 ){
        current_angle = current_angle - 360;
    }
    if ( current_angle < -360 ){
        current_angle = current_angle + 360;
    }

    this.setAnimation(anim);
    this.invalidate();  //Calls onDraw()

}

这解决了onDraw不断被调用的问题,但它创建了另一个:当用户推动,保持并转动ImageView时,它在零角度和当前角度之间来回捕捉。当用户然后放开ImageView时,它会快速回到零角度。当用户不提供输入时,也希望始终在变量current_angle处旋转ImageView。

我尝试过不同版本的anim.setFillAfter(true),anim.setFillEnabled(true),invalidate()和this.startAnimation(anim),但它们似乎从未对此问题产生任何影响。

调用this.setAnimation(anim)的最佳位置在哪里?

1 个答案:

答案 0 :(得分:0)

我可能建议不要使用Animation框架将静态转换应用于视图,这样您就不必每次都应用新Animation时处理由重置引起的问题。 / p>

如果您要旋转的内容仅包含图像,请考虑将图像包裹在RotateDrawable中,并将其设置为ImageView的内容。通过这种方式,您可以通过设置其级别值(Drawable.setLevel()ImageView.setImageLevel()应该执行操作)来控制可绘制的旋转方式,并且转换将保持不变。如果您需要在一段时间内自动化动画,您只需调用Handler内的级别设置代码,该代码会经常发布更新。

另一种选择是创建自定义ViewGroup并使用getChildStaticTransformation()方法将旋转应用于任何子视图(确保启用它或覆盖已启用它的子类)。 TransformationAnimation框架用于修改视图外观的内容。在这种情况下,当用户输入发生变化时,您可能仍需要调用invalidate()以强制重新绘制。如果您想要定期自动执行更改,则适用相同的Handler规则。

RotateDrawable示例

假设您要旋转的图像位于res / drawable / wheel.png,在res / drawable / wheel_rotate.xml创建一个简单的XML文件:

<rotate xmlns:android="http://schemas.android.com/apk/res/android"
    android:drawable="@drawable/wheel"
    android:fromDegrees="0"
    android:toDegrees="360"
    android:pivotX="50%"
    android:pivotY="50%" />

将图片打包成RotateDrawable。然后,在您的Java代码集中,可绘制为ImageView的内容:

ImageView wheel;
//You only do this once
wheel.setImageResource(R.drawable.wheel_rotate);

//Adjust the progress any time you need to by adjusting the drawable's level
wheel.setImageLevel(500);

默认情况下,级别范围为0到10,000。因此映射到0 level = fromDegrees和10,000 level = toDegrees。

HTH