Анимировать переход между фрагментами - PullRequest
266 голосов
/ 08 февраля 2011

Я пытаюсь оживить переход между фрагментами. Я получил ответ от следующего
Фрагменты Android и анимация

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

И мой R.anim.slide_in_left

<?xml version="1.0" encoding="utf-8"?>
<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>

Но когда я попробовал это, он показал

02-08 16:27:37.961: ERROR/AndroidRuntime(1717): FATAL EXCEPTION: main
02-08 16:27:37.961: ERROR/AndroidRuntime(1717): java.lang.RuntimeException: Unknown animator name: translate
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:129)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:126)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:93)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:72)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.loadAnimator(FragmentManager.java:621)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:733)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:919)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.BackStackRecord.run(BackStackRecord.java:578)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1217)

Есть идеи? Когда я проверял Honeycomb API, ссылка translate была там. Что я пропустил?
Есть ли другой способ оживить переход между фрагментами? Спасибо

Ответы [ 8 ]

337 голосов
/ 08 февраля 2011

Вам необходимо использовать новый android.animation каркас (аниматоры объектов) с FragmentTransaction.setCustomAnimations, а также FragmentTransaction.setTransition.

Вот пример использования setCustomAnimations из ApiDemos ' FragmentHideShow.java :

ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);

и вот соответствующий аниматор XML из res / animator / fade_in.xml :

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_quad"
    android:valueFrom="0"
    android:valueTo="1"
    android:propertyName="alpha"
    android:duration="@android:integer/config_mediumAnimTime" />

Обратите внимание, что вы можете объединить несколько аниматоров, используя <set>, так же, как вы могли бы использовать более раннюю анимационную среду.


РЕДАКТИРОВАТЬ : Поскольку люди спрашивают о включении / выключении, я прокомментирую это здесь.

Выдвижной и выдвижной

Вы, конечно, можете анимировать свойства translationX, translationY, x и y, но, как правило, слайды включают анимацию контента на экране и за его пределами. Насколько я знаю, нет никаких свойств перехода, которые используют относительные значения. Однако это не мешает вам писать их самостоятельно. Помните, что для анимации свойств просто требуются методы getter и setter для объектов, которые вы анимируете (в данном случае представлений), так что вы можете просто создать свои собственные getXFraction и setXFraction методы для вашего подкласса представления, как это:

public class MyFrameLayout extends FrameLayout {
    ...
    public float getXFraction() {
        return getX() / getWidth(); // TODO: guard divide-by-zero
    }

    public void setXFraction(float xFraction) {
        // TODO: cache width
        final int width = getWidth();
        setX((width > 0) ? (xFraction * width) : -9999);
    }
    ...
}

Теперь вы можете анимировать свойство xFraction, например:

Рез / аниматор / slide_in.xml

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:valueFrom="-1.0"
    android:valueTo="0"
    android:propertyName="xFraction"
    android:duration="@android:integer/config_mediumAnimTime" />

Обратите внимание, что если объект, в котором вы анимируете, не имеет такой же ширины, что и его родительский объект, все будет выглядеть не совсем правильно, поэтому вам может потребоваться настроить реализацию свойства в соответствии с вашим вариантом использования.

160 голосов
/ 30 ноября 2015

Я сделал так:

Добавить этот метод в заменить фрагменты на Анимации :

public void replaceFragmentWithAnimation(android.support.v4.app.Fragment fragment, String tag){
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
    transaction.replace(R.id.fragment_container, fragment);
    transaction.addToBackStack(tag);
    transaction.commit();
}

Вы должны добавить четыре анимации в анимацию папку, которая связана с ресурсом :

enter_from_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="-100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>

exit_to_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>

enter_from_right.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>

exit_to_left.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="-100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>

Выход:

enter image description here

Готово .

49 голосов
/ 23 января 2015

Если вы можете позволить себе привязать себя только к леденцу на палочке и позже, похоже, это поможет:

import android.transition.Slide;
import android.util.Log;
import android.view.Gravity;
.
.
.
f = new MyFragment();
f.setEnterTransition(new Slide(Gravity.RIGHT));
f.setExitTransition(new Slide(Gravity.LEFT));
getFragmentManager()
    .beginTransaction()
    .replace(R.id.content, f, FRAG_TAG)  // FRAG_TAG is the tag for your fragment
    .commit();

Надеюсь, это поможет.

47 голосов
/ 07 марта 2013

Nurik ответ был очень полезным, но я не мог заставить его работать, пока не нашел this . Короче говоря, если вы используете библиотеку совместимости (например, SupportFragmentManager вместо FragmentManager), синтаксис файлов анимации XML будет другим.

26 голосов
/ 29 октября 2014

Вот анимация слайда ввода / вывода между фрагментами:

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.animator.enter_anim, R.animator.exit_anim);
transaction.replace(R.id.listFragment, new YourFragment());
transaction.commit();

Мы используем objectAnimator.

Вот два XML-файла в подпапке animator .

enter_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
     <objectAnimator
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:duration="1000"
         android:propertyName="x"
         android:valueFrom="2000"
         android:valueTo="0"
         android:valueType="floatType" />
</set>

exit_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:propertyName="x"
        android:valueFrom="0"
        android:valueTo="-2000"
        android:valueType="floatType" />
</set>

Надеюсь, это кому-нибудь поможет.

20 голосов
/ 13 февраля 2017

Для всех, кого поймают, убедитесь, что setCustomAnimations вызывается перед вызовом для замены / добавления при построении транзакции.

12 голосов
/ 20 апреля 2013

Реализация FragmentTransaction для Android SDK требует Animator, в то время как библиотека поддержки хочет Animation, не спрашивайте меня, почему, но после комментария странного лука я изучил код Android 4.0.3 и библиотеку поддержки. Android SDK использует loadAnimator(), а библиотека поддержки использует loadAnimation()

5 голосов
/ 27 февраля 2018

Попробуйте использовать это простое и быстрое решение. Android предоставляет некоторые значения по умолчанию animation s.

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

Выход:

enter image description here

...