Анимация setVisibility GONE/VISIBLE

282
12 января 2017, 04:44

Как сделать, чтобы при скрытии нескольких View-элементов, находящихся рядом в LinearLayout было так:

  1. View-элементы одновременно плавно выцветают.
  2. Все, что было под ними, плавно сдвигается вверх на их место.

И аналогично для setVisibility(View.GONE).

Пробовал использовать animateLayoutChanges="true" - не срабатывает.

Answer 1

Задачу можно решить с помощью ViewPropertyAnimator. Возьмем для примера LinearLayout с тремя элементами:

<LinearLayout
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="ru.jollydroid.propertyanimationdisappearance.MainActivity">
    <TextView
        android:id="@+id/one"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#ff0000"
        android:padding="16dp"
        android:text="One"
        android:textColor="#00ffff"/>
    <TextView
        android:id="@+id/two"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#00ff00"
        android:padding="16dp"
        android:text="Two"
        android:textColor="#ff00ff"/>
    <TextView
        android:id="@+id/three"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:background="#0000ff"
        android:padding="16dp"
        android:text="Three"
        android:textColor="#ffff00"/>
</LinearLayout>

Как бы мы сделали без анимации?

two.setVisibility(View.GONE);

Что это дает? Элемент two исчезает, элемент three смещается наверх на место two.

Какая нам нужна анимация? Сначала у элемента two плавно уменьшить прозрачность, затем элемент three плавно сместить наверх на высоту элемента two. Так и запишем:

void stepOne() {
    two.animate()
            .setDuration(500)
            .alpha(0)
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    stepTwo();
                }
            });
}
void stepTwo() {
    three.animate()
            .setDuration(500)
            .translationY(-binding.two.getHeight())
            .setInterpolator(new AccelerateInterpolator())
            .setListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationEnd(Animator animation) {
                    stepThree();
                }
            });
}
/*
нужно в конце анимаци вернуть свойства в исходное состояние, но так,
чтобы взаимное расположение осталось неизменным
 */
void stepThree() {
    // отключаем лиснеры, на всякий случай, чтобы при следующей анимации неожиданно не сработал
    three.animate().setListener(null);
    two.animate().setListener(null);
    // сводим задачу к предыдущей
    two.setVisibility(View.GONE);
    // возвращаем свойства в исходное состояние
    three.setTranslationY(0);
    binding.two.setAlpha(1);
}

При наступлении события надо запустить stepOne().

Надо ли чистить последствия анимации на третьем шаге - решать вам. Если это разовый эффект, то надо, чтобы дальнейшая работа с интерфейсом не была неожиданной, потому что, например, элемент three так и останется смещенным относительно своего исходного положения. Если же все поведение интерфейса будет построено на анимации, то не надо, чтобы появление элемента two обратно можно было сделать аналогично исчезновению.

Про эту анимацию была статья в блоге: https://android-developers.googleblog.com/2011/05/introducing-viewpropertyanimator.html

Еще один пример использования этй же анимации есть в моей статье: http://jollydroid.ru/notebook/2016-04-05-Property-Animation-Rotation.html

Answer 2

Достаточно использовать animateLayoutChanges="true". Чтобы оно работало нужно использовать linearLayout.addView(view) чтобы добавить вьюшку с анимацией и чтобы удалить linearlayout.removeView(view).

В разделе "Курсы" есть статья: https://developer.android.com/training/animation/layout.html

Answer 3

Второй способ решения этой задачи - поменять LinearLayout на RecyclerView. Тогда можно исчезновение и появление сделать с помощью RecyclerView.ItemAnimator - написать свой или взять готовый. Тогда получится универсальное решение, которое одинаково красиво покажет исчезновение или появление любого количества элементов.

Аниматор можно оставить стандартный или найти в сторонней библиотеке: https://github.com/wasabeef/recyclerview-animators

READ ALSO
Подскажите методы выведения на экран с помощью блока If [требует правки]

Подскажите методы выведения на экран с помощью блока If [требует правки]

Нужно сделать так, что если наступает определённое время, то на экране выводится, что принимает другой врачМожно ли написать как-то с помощью...

255
Условие IN в запросе к Dynamo DB

Условие IN в запросе к Dynamo DB

Здравствуйте, как сделать вместо Id = :first OR Id = :second условие с использование IN ?

271
Как определить расширение файла?

Как определить расширение файла?

Я пытаюсь сделать свой файловый менеджер и столкнулся с такой проблемойКогда я пытаюсь выбрать файл, а не директорию, то моя программа слетает

306