@@@@@@@@@@@@@@@@@@@@@@@@@@@
EDIT: ho finito per non implementare questa soluzione perché c'erano altri problemi che questo ha. Square ha recentemente pubblicato 2 librerie che sostituiscono i frammenti. Direi che questa potrebbe effettivamente essere un'alternativa migliore rispetto al tentativo di hackerare i frammenti per fare qualcosa che Google non vuole che facciano.
http://corner.squareup.com/2014/01/mortar-and-flow.html
@@@@@@@@@@@@@@@@@@@@@@@@@@@
Ho pensato che avrei messo a punto questa soluzione per aiutare le persone che hanno questo problema in futuro. Se segui la conversazione dei poster originali con altre persone e guardi il codice che ha pubblicato, vedrai che il poster originale alla fine giunge alla conclusione di utilizzare un'animazione non operativa sui frammenti figlio mentre anima il frammento genitore. Questa soluzione non è l'ideale in quanto ti obbliga a tenere traccia di tutti i frammenti figlio, che possono essere complicati quando si utilizza un ViewPager con FragmentPagerAdapter.
Dato che uso Child Fragments dappertutto, ho escogitato questa soluzione che è efficiente e modulare (quindi può essere facilmente rimossa) nel caso in cui lo aggiustassero e questa animazione non operativa non fosse più necessaria.
Ci sono molti modi per implementarlo. Ho scelto di utilizzare un singleton e lo chiamo ChildFragmentAnimationManager. Fondamentalmente terrà traccia di un frammento di bambino per me in base al suo genitore e applicherà un'animazione no-op ai bambini quando richiesto.
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;
}
}
Successivamente è necessario disporre di una classe che estenda Fragment estendendo tutti i tuoi Fragments (almeno i tuoi Child Fragments). Ho già avuto questa classe e la chiamo BaseFragment. Quando viene creata una vista frammenti, la aggiungiamo a ChildFragmentAnimationManager e la rimuoviamo quando viene distrutta. Puoi farlo su Attacco / Scollega o altri metodi di corrispondenza nella sequenza. La mia logica per scegliere Crea / Distruggi vista era perché se un frammento non ha una vista, non mi interessa animarlo per continuare a essere visto. Questo approccio dovrebbe funzionare meglio anche con ViewPagers che usano Fragments in quanto non terrai traccia di ogni singolo Fragment che contiene un FragmentPagerAdapter, ma piuttosto solo 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();
}
}
Ora che tutti i tuoi frammenti sono archiviati in memoria dal frammento genitore, puoi chiamare animate su di essi in questo modo ei frammenti di tuo figlio non scompariranno.
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();
Inoltre, solo così ce l'hai, ecco il file no_anim.xml che va nella tua cartella 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>
Ancora una volta, non penso che questa soluzione sia perfetta, ma è molto meglio che per ogni istanza hai un frammento figlio, che implementa codice personalizzato nel frammento genitore per tenere traccia di ogni figlio. Ci sono stato e non è divertente.
R.id.fragmentHolder
rispetto ad A, A1, A2, ecc.?