Анимация фрагментации: слайд и слайд

Я проверил некоторые учебные пособия для анимации транзакций между фрагментами. Я использовал этот метод для анимации:

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

И это работает. Но я хочу, чтобы анимация была инвертирована: старый фрагмент скользит влево, а новый фрагмент сдвигается вправо, но никакое значение файла R.anim, по-видимому, не является полезным для моей области. Как мне это сделать?

Solutions Collecting From Web of "Анимация фрагментации: слайд и слайд"

UPDATE Для Android v19 + см. Эту ссылку через @Sandra

Вы можете создавать свои собственные анимации. Размещение анимационных XML-файлов в res > anim

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> 

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> 

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> 

ИСПОЛЬЗОВАНИЕ (обратите внимание, что порядок, в котором вы называете методы транзакции, имеет значение. Добавьте анимацию до вызова .replace, .commit):

 FragmentTransaction transaction = supportFragmentManager.beginTransaction(); transaction.setCustomAnimations(R.anim.enter_from_right, R.anim.exit_to_left); transaction.replace(R.id.content_frame, fragment); transaction.addToBackStack(null); transaction.commit(); 

Это еще одно решение, которое я использую:

 public class CustomAnimator { private static final String TAG = "com.example.CustomAnimator"; private static Stack<AnimationEntry> animation_stack = new Stack<>(); public static final int DIRECTION_LEFT = 1; public static final int DIRECTION_RIGHT = -1; public static final int DIRECTION_UP = 2; public static final int DIRECTION_DOWN = -2; static class AnimationEntry { View in; View out; int direction; long duration; } public static boolean hasHistory() { return !animation_stack.empty(); } public static void reversePrevious() { if (!animation_stack.empty()) { AnimationEntry entry = animation_stack.pop(); slide(entry.out, entry.in, -entry.direction, entry.duration, false); } } public static void clearHistory() { animation_stack.clear(); } public static void slide(final View in, View out, final int direction, long duration) { slide(in, out, direction, duration, true); } private static void slide(final View in, final View out, final int direction, final long duration, final boolean save) { ViewGroup in_parent = (ViewGroup) in.getParent(); ViewGroup out_parent = (ViewGroup) out.getParent(); if (!in_parent.equals(out_parent)) { return; } int parent_width = in_parent.getWidth(); int parent_height = in_parent.getHeight(); ObjectAnimator slide_out; ObjectAnimator slide_in; switch (direction) { case DIRECTION_LEFT: default: slide_in = ObjectAnimator.ofFloat(in, "translationX", parent_width, 0); slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, -out.getWidth()); break; case DIRECTION_RIGHT: slide_in = ObjectAnimator.ofFloat(in, "translationX", -out.getWidth(), 0); slide_out = ObjectAnimator.ofFloat(out, "translationX", 0, parent_width); break; case DIRECTION_UP: slide_in = ObjectAnimator.ofFloat(in, "translationY", parent_height, 0); slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, -out.getHeight()); break; case DIRECTION_DOWN: slide_in = ObjectAnimator.ofFloat(in, "translationY", -out.getHeight(), 0); slide_out = ObjectAnimator.ofFloat(out, "translationY", 0, parent_height); break; } AnimatorSet animations = new AnimatorSet(); animations.setDuration(duration); animations.playTogether(slide_in, slide_out); animations.addListener(new Animator.AnimatorListener() { @Override public void onAnimationCancel(Animator arg0) { } @Override public void onAnimationEnd(Animator arg0) { out.setVisibility(View.INVISIBLE); if (save) { AnimationEntry ae = new AnimationEntry(); ae.in = in; ae.out = out; ae.direction = direction; ae.duration = duration; animation_stack.push(ae); } } @Override public void onAnimationRepeat(Animator arg0) { } @Override public void onAnimationStart(Animator arg0) { in.setVisibility(View.VISIBLE); } }); animations.start(); } } 

Использование класса. Допустим, у вас есть два фрагмента (фрагменты списка и деталей), как показано ниже

 <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/ui_container" android:layout_width="match_parent" android:layout_height="match_parent" > <FrameLayout android:id="@+id/list_container" android:layout_width="match_parent" android:layout_height="match_parent" /> <FrameLayout android:id="@+id/details_container" android:layout_width="match_parent" android:layout_height="match_parent" android:visibility="gone" /> </FrameLayout> 

Применение

 View details_container = findViewById(R.id.details_container); View list_container = findViewById(R.id.list_container); // You can select the direction left/right/up/down and the duration CustomAnimator.slide(list_container, details_container,CustomAnimator.DIRECTION_LEFT, 400); 

Вы можете использовать функцию CustomAnimator.reversePrevious(); Чтобы получить предыдущее представление, когда пользователь нажал назад.