Property Animation — появившаяся в Android 3.0 система анимации свойств любых объектов. Эта история о том, как с помощью Property Animation показать поворот карточки тыльной стороной к зрителю и обратно.

Screenshot 1

Карточку проще всего сделать с помощью TextView с непрозрачным фоном. Две стороны карточки — два TextView, один из них невидимый. Я буду менять один TextView на другой так, чтобы это выглядело как вращение листа вокруг вертикальной оси.

Делаем два TextView, по одному на каждую сторону карточки. Для наглядности эксперимента один будет с зеленым фоном, второй — с красным. Так их и назовем. Вначале виден зеленый.

<FrameLayout
    android:id="@+id/box"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
 
    <TextView
        android:id="@+id/red"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="70dp"
        android:background="#ff0000"
        android:gravity="center"
        android:text="Two"
        android:visibility="gone"/>
     
    <TextView
        android:id="@+id/green"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:layout_margin="70dp"
        android:background="#00ff00"
        android:gravity="center"
        android:text="One"/>
 
</FrameLayout>

Привычная рутина:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
     
    green = (TextView) findViewById(R.id.green);
    red = (TextView) findViewById(R.id.red);
     
    green.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
              grin2red();
          }
    });
}

Исследуем ViewPropertyAnimator для анимации поворота:

public void grin2red() {
    green.animate()
        .setDuration(500)
        .rotationY(180);
}

Выводы:

  • Ось вращения проходит через середину элемента. Неожиданно, но очень удачно.
  • При завершении анимации элемент остается в конечном положении (в исходное состояние не возвращается). Поэтому повторный клик ни к чему не приводит.
  • При угле 90° элемент невидим. Это хороший момент подменить зеленый на красный.

Итак, дальнейший план такой:

  • Поворачиваем зеленую TextView на 90°.
  • Подменяем TextView зеленую на красную.
  • Продолжаем поворачивать в ту же сторону еще на 90°. Красный TextView должен занять свое обычное положение.

Обычное положение — 0°. Значит, начальное положение для красного TextView, когда он к нам боком, равно -90°. Пробуем:

public void grin2red() {
    green.setRotationY(0);
    red.setVisibility(View.INVISIBLE);
    red.setRotationY(-90);
     
    green.animate()
        .setDuration(DURATION)
        .rotationY(90)
        .setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                red.setVisibility(View.VISIBLE);
                green.setVisibility(View.GONE);
                 
                red.animate()
                    .setDuration(DURATION)
                    .rotationY(0);
            }
        });
}

Годится. И в обратную сторону:

public void red2green() {
    red.setRotationY(0);
    green.setVisibility(View.INVISIBLE);
    green.setRotationY(90);
     
    red.animate()
        .setDuration(DURATION)
        .rotationY(-90)
        .setListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                red.setVisibility(View.GONE);
                green.setVisibility(View.VISIBLE);
                 
                green.animate()
                    .setDuration(DURATION)
                    .rotationY(0);
            }
        });
}

Кроме этого нужно:

  • Добавить интерполятор, чтобы движение было более естественным.
  • Отменить в конце анимации все лиснеры. Иначе при следующем повороте они тоже будут срабатывать.

Это уже смотрите в коде.

Пример

Github https://github.com/JollyDroidNotebook/PropertyAnimationRotation

Ссылки