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