安卓旋转ImageView,我无法在onAnimationEnd()中设置ImageView的最终位置

9

我想在每次点击按钮时将ImageView旋转30度。

第一次单击时,我可以正确设置动画,但我无法成功更新动画后的ImageView位置。当我再次单击按钮时,动画从ImageView的原始位置开始而不是从第一个动画后的最终位置开始。

这是我的代码:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    turnImg = (ImageView) findViewById(R.id.imageViewturnImg );
    Bitmap bmp = BitmapFactory.decodeResource(getResources(), R.drawable.imgTurn);
    // Getting width & height of the given image.
    int w = bmp.getWidth();
    int h = bmp.getHeight();

    turnImg .setImageBitmap(bmp);

    Button buttonok = (Button) findViewById(R.id.buttonok);
    buttonok.setOnClickListener(new OnClickListener() {
        public void onClick(View v) {
            turn();
        }
    });

}

public void turn()
{
    float degrees = 30; 

    RotateAnimation anim = new RotateAnimation(0, degrees,Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);
    anim.setInterpolator(new LinearInterpolator());
    anim.setDuration(300);
    anim.setFillEnabled(true);

    anim.setFillAfter(true);

    anim.setAnimationListener(new AnimationListener() {
        @Override
        public void onAnimationEnd(Animation arg0) {

        Matrix mat = turnImg.getImageMatrix();
            mat.postRotate(30,turnImg.getWidth()/2, turnImg.getHeight()/2);
            turnImg.setScaleType(ScaleType.MATRIX);
            turnImg.setImageMatrix(mat);

        }

        @Override
        public void onAnimationRepeat(Animation animation) {}
        @Override
        public void onAnimationStart(Animation animation) {}
    });


    turnImg.startAnimation(anim);

}

我认为问题出在我在onAnimationEnd()中实现位置的方式上。

附注:对不起我的英语不好...


事实是,在旋转真实图像后,“填充后”应该被取消。我尝试通过在onAnimationEnd()中添加一行turnImg.clearAnimation()来实现,但我得到了一个可怕的故障(至少在模拟器上),就像如果你只删除填充后一样。 - bigstones
我在想,也许问题是由于setScaleType(ScaleType.MATRIX)引起的; 在我的xml中,ImageView turnImg被设置为android:scaleType =“center”。 - colorado
你在代码中设置的内容会覆盖你在xml中设置的内容,所以不会有冲突。由于你是通过编程方式创建动画,因此可能会将最后达到的角度作为起始角度创建动画,并且使用“填充后”而不进行矩阵旋转。但我不知道它在角度大于360°时的行为如何。 - bigstones
1个回答

16
问题在于您的动画没有影响与矩阵旋转相同的对象。也就是说,您正在动画化ImageView对象的旋转,但然后您设置了该ImageView对象内部图像的旋转。因此,例如,第一次旋转时,ImageView从0度旋转到30度,然后由于调用setFillAfter(true)而保持在30度的旋转状态。然后运行onAnimationEnd()处理程序,它将内部图像旋转30度。这实际上使得用户看到图像跳到了60度的旋转角度(View为30度,位图为30度)。然后下一次动画运行时,它将视图从0度旋转到30度,内部图像仍处于其30度的旋转状态。这使得用户观察到它看起来像是从30度旋转到60度。然后当动画完成时,对内部图像应用另一个旋转,最终图像被旋转到60度,而视图(再次)旋转到30度,因此图像现在在视觉上旋转了90度。

等等。

有不同的方法来解决这个问题,但一个简单的方法是避免影响两个不同的对象-只使用ImageView。不要每次从0到30旋转,而是从当前旋转角度旋转到该值加上30度。您可以删除onAnimationEnd()处理程序,因为您将不再需要旋转视图内部的图像。

turn()的结果代码要简单得多:

public void turn()
{
    RotateAnimation anim = new RotateAnimation(currentRotation, currentRotation + 30,
            Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF,0.5f);
    currentRotation = (currentRotation + 30) % 360;

    anim.setInterpolator(new LinearInterpolator());
    anim.setDuration(1000);
    anim.setFillEnabled(true);

    anim.setFillAfter(true);
    turnImg.startAnimation(anim);
}

这段代码假设一个实例变量currentRotation,用于跟踪视图上一次旋转的度数。

如果允许用户在动画进行中点击,那么就需要更多的处理,但不会太麻烦。

顺便说一句,在3.0版本中的动画系统要简单得多;现在View有一个“rotation”属性,可以在该属性上运行动画并跟踪其自身当前值。但是上面的方法适用于旧版本。


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