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

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

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

5 ответов

Решение

Для анимации перехода между фрагментами или для анимации процесса отображения или скрытия фрагмента вы используете 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>

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

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

Изучив ответы Рето и слепых, я получил следующий код.

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

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

Пожалуйста, используйте это, я думаю, что гораздо лучшие решения.Android Studio обеспечивает по умолчанию animation,

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

Выход:

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

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

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

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

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

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()
            }
        }
    }
}

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

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment
Другие вопросы по тегам