Android повернуть изображение, я не могу установить конечную позицию изображения в onAnimationEnd () - PullRequest
9 голосов
/ 08 мая 2011

Я хочу поворачивать изображение на 30 градусов при каждом нажатии кнопки.

При первом щелчке я могу правильно настроить анимацию, но мне не удается обновить позицию просмотра изображения после анимации. Когда я снова нажал на кнопку, анимация начинается с исходной позиции просмотра изображения, а не с конечной позиции после первой анимации.

Вот мой код:

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 ().

ps: извините за мой плохой английский ...

1 Ответ

16 голосов
/ 14 мая 2011

Проблема в том, что ваша анимация не влияет на тот же объект, что и вращение вашей матрицы.То есть вы анимируете вращение объекта ImageView, но затем вы устанавливаете вращение изображения, которое находится внутри этого объекта ImageView.Так, например, при первом повороте ImageView поворачивается от 0 до 30 градусов, а затем остается на 30 градусов из-за вызова setFillAfter (true).Затем запускается обработчик onAnimationEnd (), который поворачивает внутреннее изображение на 30 градусов.Это эффективно перемещает изображение до поворота на 60 градусов, как видно пользователю (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 теперь есть свойство 'revolution', и вы можете запустить анимацию для этого свойства, и оно может отслеживать свое собственное текущее значение.Но описанный выше подход должен работать для более старых версий.

...