@@@@@@@@@@@@@@@@@@@@@@@@@@
EDIT: J'ai fini par désimplémenter cette solution car il y avait d'autres problèmes que cela posait. Square a récemment sorti 2 bibliothèques qui remplacent des fragments. Je dirais que cela pourrait en fait être une meilleure alternative que d'essayer de pirater des fragments pour faire quelque chose que Google ne veut pas qu'ils fassent.
http://corner.squareup.com/2014/01/mortar-and-flow.html
@@@@@@@@@@@@@@@@@@@@@@@@@@
J'ai pensé que je proposerais cette solution pour aider les personnes qui auront ce problème à l'avenir. Si vous retracez la conversation des affiches originales avec d'autres personnes et que vous regardez le code qu'il a publié, vous verrez que l'affiche originale arrive finalement à la conclusion de l'utilisation d'une animation sans opération sur les fragments enfants tout en animant le fragment parent. Cette solution n'est pas idéale car elle vous oblige à garder une trace de tous les fragments enfants, ce qui peut être fastidieux lors de l'utilisation d'un ViewPager avec FragmentPagerAdapter.
Depuis que j'utilise Child Fragments partout, j'ai proposé cette solution qui est efficace et modulaire (afin qu'elle puisse être facilement supprimée) au cas où ils le répareraient un jour et que cette animation sans opération ne serait plus nécessaire.
Il existe de nombreuses façons de mettre cela en œuvre. J'ai choisi d'utiliser un singleton, et je l'appelle ChildFragmentAnimationManager. Il gardera essentiellement une trace d'un fragment enfant pour moi en fonction de son parent et appliquera une animation sans opération aux enfants lorsqu'on le lui demandera.
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;
}
}
Ensuite, vous devez avoir une classe qui étend Fragment que tous vos fragments étendent (au moins vos fragments enfants). J'avais déjà cette classe, et je l'appelle BaseFragment. Lorsqu'une vue de fragments est créée, nous l'ajoutons à ChildFragmentAnimationManager, et nous la supprimons lorsqu'elle est détruite. Vous pouvez le faire onAttach / Detach ou d'autres méthodes de correspondance dans la séquence. Ma logique pour choisir Créer / Détruire une vue était parce que si un fragment n'a pas de vue, je ne me soucie pas de l'animer pour continuer à être vu. Cette approche devrait également mieux fonctionner avec les ViewPagers qui utilisent des fragments, car vous ne garderez pas trace de chaque fragment qu'un FragmentPagerAdapter contient, mais plutôt de 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();
}
}
Maintenant que tous vos fragments sont stockés en mémoire par le fragment parent, vous pouvez appeler animate sur eux comme ceci, et vos fragments enfants ne disparaîtront pas.
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();
Aussi, pour que vous l'ayez, voici le fichier no_anim.xml qui va dans votre dossier 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>
Encore une fois, je ne pense pas que cette solution soit parfaite, mais elle est bien meilleure que pour chaque instance, vous avez un fragment enfant, implémentant un code personnalisé dans le fragment parent pour suivre chaque enfant. J'y suis allé et ce n'est pas amusant.
R.id.fragmentHolder
par rapport à A, A1, A2, etc.?