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

265

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

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

alexanderblom
источник

Ответы:

388

Для анимации перехода между фрагментами или для анимации процесса отображения или скрытия фрагмента вы используете 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>
Рето Мейер
источник
57
Когда я попробовал это, он показывает RuntimeException: Неизвестное имя аниматора: перевод .
Лабиб Панампуллан
3
Убедитесь, что анимации, определенные в slide_in_left и right, созданы с использованием набора определений objectAnimator, а не старого определения анимации.
Рето Мейер
7
Это очень помогло. Я был на правильном пути, но просто не прошел весь путь. Для других читателей вы также можете использовать андроид: интерполятор в качестве атрибута, указав свой любимый (например, «@android: интерполятор / линейный»). По умолчанию используется значение @android: interpolator / accelerate_decelerate.
Дэйв Маклин
6
Я нацеливаюсь на API Level 7 с API совместимости. Есть ли способ для меня, чтобы оживить фрагменты?
Джаррод Смит
5
@JarrodSmith, вы можете попробовать использовать библиотеку совместимости, такую ​​как NineOldAndroids, чтобы перенести Honeycomb API в Eclair.
Мистер С
249

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

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

После консультации Рета и blindstuff - ые ответов я получил следующий код работать.

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

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-й версии библиотеки поддержки.

dmanargias
источник
47
Это только спасло меня. Обратите внимание , важно обратить внимание на порядок , который, естественно, я пропустил с первого раза. Это означает, что вы должны вызвать setCustomAnimations () перед replace ().
Стивен Кидсон
3
Я пытался реализовать свои фрагменты. Я написал все, как вы упомянули, но logcat говорит: неизвестное имя аниматора translate Как я могу преодолеть эту проблему? Кстати, я называю свой фрагмент в «Навигационном ящике» («Скользящее меню»)
Зафер Челалоглу,
Прекрасно работает, но оказывается, что сборка с использованием инструментов сборки 21.1 генерирует ошибку, говорящую «Неверное имя файла: должно содержать только строчные буквы и цифры ([a-z0-9_.])». Я предлагаю отредактировать имена файлов в ответе на pop_enter.xml и pop_exit.xml.
Смичак
Отличное решение, и оно прекрасно работает, когда я нажимаю кнопку возврата. У меня только один вопрос: если я хочу создать пользовательскую кнопку BackButton, какой код я должен вызвать, чтобы повторить поведение кнопки назад?
Томас Тейлманн
1
Томас, если ты хочешь вернуться, ты должен реализовать эту форму: .setCustomAnimations (R.anim.pop_enter, R.anim.pop_exit, R.anim.enter, R.anim.exit)
Алекс Зараос
26

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

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

Вывод:

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

Gowthaman M
источник
1
android.R ... "Android Studio предоставляет анимацию по умолчанию", это не для android studio, она также может работать в затмении, android.R специфична для android. И, кстати, вы не поделились информацией, что такое apis. Потому что вещи на android.R разные на разных apis.
Стив Моретц
@stevemoretz thaxs bro Я согласился с твоей точкой зрения. Я исправлю и обновлю свой ответ ...
Gowthaman M
5

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

mark.kedzierski
источник
2

Что касается меня, мне нужно посмотреть направление:

в -> проведите справа

вне -> проведите влево

Вот у меня работает код:

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()
            }
        }
    }
}
Серг Бурлака
источник
Android, кажется, мерцает переходы с этими анимациями (особенно с переводом)
Габриэль Де Оливейра
@GabrielDeOliveiraRohden как по мне не во всех смыслах
Сергей Бурлака
1

Я решаю это следующим образом

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
Шакават Хоссейн
источник