Фрагменты и анимация Android

Как вы должны реализовать вид скольжения, который, например, использует клиент Gmail Honeycomb?

Может TransactionManager справиться с этим автоматически, добавляя и удаляя Фрагменты, это довольно сложно проверить из-за того, что эмулятор представляет собой слайд-шоу :)


person alexanderblom    schedule 27.01.2011    source источник


Ответы (6)


Чтобы анимировать переход между фрагментами или анимировать процесс отображения или скрытия фрагмента, вы используете Fragment Manager для создания Fragment Transaction.

Внутри каждой транзакции фрагмента вы можете указать анимацию входа и выхода, которая будет использоваться для отображения и скрытия соответственно (или того и другого, если используется замена).

В следующем коде показано, как заменить фрагмент, выдвинув один фрагмент и сдвинув другой на его место.

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();

Чтобы добиться того же, скрывая или показывая фрагмент, вы просто вызываете ft.show или ft.hide, передавая фрагмент, который вы хотите показать или скрыть соответственно.

Для справки, определения анимации XML будут использовать тег objectAnimator. Пример slide_in_left может выглядеть примерно так:

<?xml version="1.0" encoding="utf-8"?>
<set>
  <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="x" 
    android:valueType="floatType"
    android:valueFrom="-1280"
    android:valueTo="0" 
    android:duration="500"/>
</set>
person Reto Meier    schedule 27.01.2011
comment
Когда я попробовал это, он показывает RuntimeException: Unknown animator name: translate. - person Labeeb Panampullan; 08.02.2011
comment
Убедитесь, что анимации, определенные в slide_in_left и right, созданы с использованием набора определений objectAnimator, а не старого определения анимации. - person Reto Meier; 09.02.2011
comment
@Dave: Добавил пример к ответу. - person Reto Meier; 27.02.2011
comment
Это очень помогло. Я был на правильном пути, но не дошел до конца. Для других читателей у вас также может быть android: interpolator в качестве атрибута с указанием вашего любимого (например, @android: interpolator / linear). По умолчанию это @android: interpolator / accelerate_decelerate. - person Dave MacLean; 28.02.2011
comment
Это не работает с api совместимости. Приложение выйдет из строя при попытке накачать objectAnimator на устройствах с уровнем API ‹11. - person Alexey; 12.10.2011
comment
что, если кто-то хочет применить собственную анимацию? способ подачи заявки на другие представления с помощью метода startAnimation - person 2cupsOfTech; 15.02.2012
comment
Что делать, если я хочу перевести с 0% на 100%? Это поддерживалось объектом translate, но я не могу использовать старые анимации с FragmentTransaction. Также, если я использую objectAnimator, будет ли он работать на устройствах ниже API 11? - person ffleandro; 29.02.2012
comment
Я нацелен на API уровня 7 с API совместимости. Есть ли способ анимировать фрагменты? - person Jarrod Smith; 16.03.2012
comment
@JarrodSmith, вы можете попробовать использовать библиотеку совместимости, например NineOldAndroids, чтобы перенести Honeycomb API в Eclair. - person Mr. S; 28.04.2012
comment
Если вы хотите сделать переход, который работает как на 2.x, так и на 3.0+, сначала посмотрите здесь: stackoverflow.com/a/7892524 / 969325. - person Warpzit; 12.07.2012
comment
Когда я скрываю (), я не могу запустить анимацию. Работает только на выставке - person Jacek Kwiecień; 18.12.2012
comment
@LabeebP, это работает только при использовании библиотеки поддержки. Дополнительную информацию см. В следующем ответе: stackoverflow.com/a/9856449/435605 - person AlikElzin-kilaka; 24.04.2013
comment
Я добавил поддержку NineOldAndroids в библиотеку поддержки Google. Подробнее см. github.com/kedzie/Support_v4_NineOldAndroids. Это позволяет использовать анимацию свойств для переходов фрагментов, преобразователей страниц и некоторых других вещей. - person mark.kedzierski; 27.05.2013
comment
ObjectAnimator вызывает у меня исключение, тогда как translate анимация работает нормально. - person Alireza Mirian; 04.04.2014
comment
Nine Old не работает с фрагментом github.com/JakeWharton/NineOldAndroids/issues/43 - person Dory; 09.01.2015
comment
В случае, если это помогает другим, если вы хотите, чтобы ваша анимация переворачивалась при выходе из фрагмента, укажите все 4 параметра: ft.setCustomAnimations (R.anim.slide_in_left, R.anim.slide_out_right, R.anim.slide_in_right, R. anim.slide_out_left); - person Justin; 06.02.2015
comment
Обратите внимание, что, используя fragmentTransaction.replace(), вы можете вызвать ненужное попадание фрагментов в события жизненного цикла, когда пользователь нажимает кнопку возврата, по сравнению с fragmentTransaction.add(). Но если вы используете .add(), вы не получите такой красивой анимации :) См. Здесь: stackoverflow.com/a/ 21684520/1738090 - person w3bshark; 29.01.2016
comment
Есть ли встроенный переход, который уже используется для действий, который я могу использовать и для фрагментов? - person android developer; 29.01.2020

Если вам не нужно использовать библиотеку поддержки, ознакомьтесь с ответом Романа.

Но если вы хотите использовать библиотеку поддержки, вам нужно использовать старую структуру анимации, как описано ниже.

После консультации с Рето и слепым материалом answers У меня работает следующий код.

Фрагменты кажутся сдвигающимися вправо и сдвигающимися влево при нажатии на спину.

FragmentManager fragmentManager = getSupportFragmentManager();

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);

CustomFragment newCustomFragment = CustomFragment.newInstance();
transaction.replace(R.id.fragment_container, newCustomFragment );
transaction.addToBackStack(null);
transaction.commit();

Порядок важен. Это означает, что вы должны вызвать setCustomAnimations() перед replace(), иначе анимация не вступит в силу!

Затем эти файлы необходимо поместить в папку res / anim.

enter.xml:

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

exit.xml:

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="-100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_enter.xml:

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="-100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_exit.xml:

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

Продолжительность анимации может быть изменена на любое из значений по умолчанию, таких как @android:integer/config_shortAnimTime или любое другое число.

Обратите внимание: если между заменами фрагментов происходит изменение конфигурации (например, вращение), обратное действие не анимируется. Это задокументированная ошибка, которая все еще существует в версии 20 из библиотека поддержки.

person dmanargias    schedule 05.07.2013
comment
Это меня просто спасло. Обратите внимание, обратите внимание на важен порядок, который, естественно, я упустил в первый раз. Это означает, что вы должны вызвать setCustomAnimations () перед replace (). - person Stephen Kidson; 06.12.2013
comment
Я пытался реализовать на своих фрагментах. Я написал все, как вы упомянули, но logcat говорит: unknow animator name translate Как я могу решить эту проблему? Кстати, я вызываю свой фрагмент на панели навигации (скользящее меню) - person Zafer Celaloglu; 06.11.2014
comment
Отлично работает, но оказалось, что при построении этого с помощью инструментов сборки 21.1 возникает ошибка: Недопустимое имя файла: должно содержать только строчные буквы и цифры ([a-z0-9_.]). Предлагаю отредактировать имена файлов в ответах на pop_enter.xml и pop_exit.xml. - person smichak; 25.01.2015
comment
Отличное решение, и оно отлично работает, когда я нажимаю кнопку возврата. У меня только один вопрос: если я хочу создать настраиваемую кнопку backButton, какой код мне следует вызвать, чтобы воспроизвести поведение кнопки возврата? - person Thomas Teilmann; 05.03.2015
comment
Thomas, если вы хотите вернуться, вы должны реализовать эту форму: .setCustomAnimations (R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit) - person Alex Zaraos; 15.06.2015
comment
@dmanargias, это решение у меня тоже работает. Я даже пробовал скользить вверх / вниз и плавно переходить в / из. Но у меня белый экран, когда фрагменты анимируются. Это происходит только при установке анимации. Я пробовал с фиктивным фрагментом, чтобы проверить, не из-за ли задержки в создании представления. Но и в этом случае виден белый экран. Кто-нибудь еще сталкивался с подобной проблемой - person Sangeetha Pinto; 09.12.2016
comment
Отличный ответ .. !! Работает отлично - person Arunjith R S; 06.11.2018

Я настоятельно рекомендую вам использовать это вместо создания файла анимации, потому что это гораздо лучшее решение. Android Studio уже предоставляет значение по умолчанию animation, которое вы можете использовать без создания нового XML-файла. Имена анимаций: android.R.anim.slide_in_left и android.R.anim.slide_out_right, и вы можете использовать их следующим образом:

fragmentTransaction.setCustomAnimations (android.R.anim.slide_in_left, android.R.anim.slide_out_right);

FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();              
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();

Вывод:

введите описание изображения здесь

person Gowthaman M    schedule 22.09.2017
comment
android.R ... Android Studio Предоставляет анимацию по умолчанию, это не для студии Android, она может работать и в eclipse, android.R зависит от Android. И, кстати, вы не поделились информацией, что это за apis. android.R разные на разных apis. - person steve moretz; 05.02.2019
comment
@stevemoretz thaxs bro Я согласен с твоей точкой зрения .. Я исправлю и обновлю свой ответ ... - person Gowthaman M; 05.02.2019

Моя модифицированная библиотека поддержки поддерживает использование как анимации просмотра (т. Е. <translate>, <rotate>), так и аниматоров объектов (т. Е. <objectAnimator>) для Фрагментные переходы. Это реализовано в NineOldAndroids. За подробностями обращайтесь к моей документации на github.

person mark.kedzierski    schedule 20.03.2014

Что касается меня, мне нужна диракция вида:

в -> проведите пальцем вправо

из -> проведите пальцем влево

Здесь у меня работает код:

slide_in_right.xml

<set xmlns:android="http://schemas.android.com/apk/res/android">
    <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
    <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>

slide_out_left.xml

 <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="0" android:toXDelta="-50%p"
                android:duration="@android:integer/config_mediumAnimTime"/>
        <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
                android:duration="@android:integer/config_mediumAnimTime" />
    </set>

код транзакции:

inline fun FragmentActivity.setContentFragment(
        containerViewId: Int,
        backStack: Boolean = false,
        isAnimate: Boolean = false,
        f: () -> Fragment

): Fragment? {
    val manager = supportFragmentManager
    return f().apply {
        manager.beginTransaction().let {
            if (isAnimate)
                it.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)

            if (backStack) {
                it.replace(containerViewId, this, "Fr").addToBackStack("Fr").commit()
            } else {
                it.replace(containerViewId, this, "Fr").commit()
            }
        }
    }
}
person Serg Burlaka    schedule 19.03.2019
comment
Android, кажется, мерцает переходы с этими анимациями (особенно переводными) - person Gabriel Rohden; 19.03.2019
comment
@GabrielDeOliveiraRohden как по мне не во всех тупиках - person Serg Burlaka; 20.03.2019

Я решаю это так, как показано ниже

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
person Shakawat Hossain    schedule 25.02.2015