Android: постоянно вызывается onDraw или анимация возвращается в исходное положение - PullRequest
0 голосов
/ 15 января 2012

Итак, мой вопрос чем-то похож на эти два вопроса:

Пользовательское представление onDraw постоянно вызывается

android: onDraw вызывается постоянно

У меня есть собственный класс, расширяющий 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, которая вызывает анимацию и т. д., вероятно, через invalidate () в классе RotateAnimation.Это правильно соблюдается?Выходные данные превосходны, поскольку ImageView всегда остается под текущим вычисленным углом, но при этом продолжаются вычисления анимации, потребляющие много энергии и мощности.

Чтобы исправить это, я попытался переместить this.setAnimation (anim) в методе, где рассчитываются параметры для анимации (пожалуйста, игнорируйте isClockWise (), calcAngleToMove () и другие вещи, не относящиеся к 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, он возвращается к нулевому углу.Желательно всегда поворачивать ImageView в переменную current_angle, даже если пользователь не вводит данные.

Я пробовал разные версии anim.setFillAfter (true), anim.setFillEnabled (true),invalidate () и this.startAnimation (anim), но, похоже, они никогда не влияют на эту проблему.

Где лучше всего вызывать this.setAnimation (anim)?

1 Ответ

0 голосов
/ 15 января 2012

Я мог бы рекомендовать не использовать каркас Animation для применения статических преобразований к представлениям, чтобы вам не приходилось сталкиваться с проблемами, вызванными сбросом при каждом применении нового Animation каждый раз.

Если содержимое, которое вы хотите повернуть, включает только изображения, рассмотрите возможность обернуть ваши изображения в RotateDrawable и установите их как содержимое вашего ImageView. При этом вы можете контролировать, как вращается ничья, устанавливая его значение уровня (либо Drawable.setLevel(), либо ImageView.setImageLevel() должно сработать), и преобразование будет придерживаться. Если вам необходимо автоматизировать анимацию на определенный период, вы можете просто вызвать код установки уровня внутри Handler, который публикует обновления так часто.

Другим вариантом будет создание пользовательского ViewGroup и использование метода getChildStaticTransformation() для применения поворота к любому дочернему представлению (обязательно включите его или переопределите подкласс, для которого он уже включен). Transformation - это то, что Animation использует также для изменения внешнего вида. В этом случае вам, вероятно, все равно придется вызывать invalidate(), когда пользовательский ввод изменился, чтобы вызвать повторное рисование. То же правило Handler будет применяться, если вы хотите периодически автоматизировать изменения.

Пример RotateDrawable

Допустим, изображение, которое вы хотите повернуть, находится по адресу res / drawable / wheel.png, создайте простой XML-файл по адресу res / drawable / wheel_rotate.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 до 10000. Так что отображается на 0 уровень = от градусов и 10000 уровень = до градусов.

НТН

...