@@@@@@@@@@@@@@@@@@@@@@@@@@@@
РЕДАКТИРОВАТЬ: я закончил тем, что не реализовал это решение, поскольку у него были другие проблемы. Square недавно выпустила 2 библиотеки, заменяющие фрагменты. Я бы сказал, что это может быть лучшая альтернатива, чем попытка взломать фрагменты, чтобы сделать что-то, чего Google не хочет, чтобы они делали.
http://corner.squareup.com/2014/01/mortar-and-flow.html
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
Я подумал, что предлагаю это решение, чтобы помочь людям, у которых возникнет эта проблема в будущем. Если вы проследите разговор с другими людьми на исходном плакате и посмотрите на опубликованный им код, вы увидите, что исходный плакат в конечном итоге приходит к выводу об использовании анимации без операции для дочерних фрагментов при анимации родительского фрагмента. Это решение не идеально, поскольку оно заставляет вас отслеживать все дочерние фрагменты, что может быть громоздким при использовании ViewPager с FragmentPagerAdapter.
Поскольку я использую дочерние фрагменты повсюду, я придумал это решение, которое является эффективным и модульным (поэтому его можно легко удалить) на случай, если они когда-либо его исправят, и эта бездействующая анимация больше не нужна.
Есть много способов реализовать это. Я решил использовать синглтон и назвал его ChildFragmentAnimationManager. Он в основном будет отслеживать дочерний фрагмент для меня на основе его родителя и будет применять анимацию без операции к дочерним элементам, когда их спросят.
public class ChildFragmentAnimationManager {
private static ChildFragmentAnimationManager instance = null;
private Map<Fragment, List<Fragment>> fragmentMap;
private ChildFragmentAnimationManager() {
fragmentMap = new HashMap<Fragment, List<Fragment>>();
}
public static ChildFragmentAnimationManager instance() {
if (instance == null) {
instance = new ChildFragmentAnimationManager();
}
return instance;
}
public FragmentTransaction animate(FragmentTransaction ft, Fragment parent) {
List<Fragment> children = getChildren(parent);
ft.setCustomAnimations(R.anim.no_anim, R.anim.no_anim, R.anim.no_anim, R.anim.no_anim);
for (Fragment child : children) {
ft.remove(child);
}
return ft;
}
public void putChild(Fragment parent, Fragment child) {
List<Fragment> children = getChildren(parent);
children.add(child);
}
public void removeChild(Fragment parent, Fragment child) {
List<Fragment> children = getChildren(parent);
children.remove(child);
}
private List<Fragment> getChildren(Fragment parent) {
List<Fragment> children;
if ( fragmentMap.containsKey(parent) ) {
children = fragmentMap.get(parent);
} else {
children = new ArrayList<Fragment>(3);
fragmentMap.put(parent, children);
}
return children;
}
}
Затем вам нужен класс, расширяющий фрагмент, который расширяют все ваши фрагменты (по крайней мере, ваши дочерние фрагменты). У меня уже был этот класс, и я назвал его BaseFragment. Когда создается представление фрагментов, мы добавляем его в ChildFragmentAnimationManager и удаляем его при уничтожении. Вы можете сделать это с помощью Attach / Detach или других методов сопоставления в последовательности. Моя логика выбора «Создать / уничтожить представление» заключалась в том, что если у фрагмента нет представления, мне не нужно его анимировать, чтобы его можно было видеть. Этот подход также должен лучше работать с ViewPager, которые используют фрагменты, поскольку вы не будете отслеживать каждый отдельный фрагмент, который удерживает FragmentPagerAdapter, а только 3.
public abstract class BaseFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
Fragment parent = getParentFragment();
if (parent != null) {
ChildFragmentAnimationManager.instance().putChild(parent, this);
}
return super.onCreateView(inflater, container, savedInstanceState);
}
@Override
public void onDestroyView() {
Fragment parent = getParentFragment();
if (parent != null) {
ChildFragmentAnimationManager.instance().removeChild(parent, this);
}
super.onDestroyView();
}
}
Теперь, когда все ваши фрагменты хранятся в памяти родительским фрагментом, вы можете вызвать для них animate, и ваши дочерние фрагменты не исчезнут.
FragmentTransaction ft = getActivity().getSupportFragmentManager().beginTransaction();
ChildFragmentAnimationManager.instance().animate(ft, ReaderFragment.this)
.setCustomAnimations(R.anim.up_in, R.anim.up_out, R.anim.down_in, R.anim.down_out)
.replace(R.id.container, f)
.addToBackStack(null)
.commit();
Кроме того, чтобы он у вас был, вот файл no_anim.xml, который находится в вашей папке res / anim:
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/linear_interpolator">
<translate android:fromXDelta="0" android:toXDelta="0"
android:duration="1000" />
</set>
Опять же, я не думаю, что это решение идеально, но оно намного лучше, чем для каждого экземпляра, который у вас есть дочерний фрагмент, реализующий собственный код в родительском фрагменте для отслеживания каждого дочернего элемента. Я был там, и это неинтересно.
R.id.fragmentHolder
относительно A, A1, A2 и т. Д.?