@@@@@@@@@@@@@@@@@@@@@@@@@@
EDYCJA: Skończyło się na tym, że nie zaimplementowałem tego rozwiązania, ponieważ były inne problemy, które ma. Niedawno wyszedł Square z 2 bibliotekami, które zastępują fragmenty. Powiedziałbym, że może to być lepsza alternatywa niż próba włamania fragmentów do zrobienia czegoś, czego Google nie chce, aby robili.
http://corner.squareup.com/2014/01/mortar-and-flow.html
@@@@@@@@@@@@@@@@@@@@@@@@@@
Pomyślałem, że zaproponuję to rozwiązanie, aby pomóc ludziom, którzy mają ten problem w przyszłości. Jeśli prześledzisz oryginalną rozmowę plakatów z innymi osobami i spojrzysz na opublikowany przez niego kod, zobaczysz, że oryginalny plakat ostatecznie kończy się użyciem animacji bez operacji na fragmentach podrzędnych podczas animowania fragmentu nadrzędnego. To rozwiązanie nie jest idealne, ponieważ zmusza Cię do śledzenia wszystkich fragmentów podrzędnych, co może być uciążliwe podczas korzystania z ViewPager z FragmentPagerAdapter.
Ponieważ wszędzie używam Child Fragments, wymyśliłem to rozwiązanie, które jest wydajne i modułowe (dzięki czemu można je łatwo usunąć) na wypadek, gdyby kiedykolwiek to naprawili, a ta animacja bez operacji nie jest już potrzebna.
Można to wdrożyć na wiele sposobów. Zdecydowałem się użyć singletona i nazywam go ChildFragmentAnimationManager. Zasadniczo będzie śledzić dla mnie fragment podrzędny na podstawie jego rodzica i zastosuje animację bez operacji do dzieci, gdy zostanie o to poproszony.
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;
}
}
Następnie musisz mieć klasę, która rozszerza Fragment, który rozszerza wszystkie twoje fragmenty (przynajmniej twoje fragmenty potomne). Miałem już tę klasę i nazywam ją BaseFragment. Po utworzeniu widoku fragmentów dodajemy go do ChildFragmentAnimationManager i usuwamy go po zniszczeniu. Możesz to zrobić na Attach / Detach lub w innych dopasowanych metodach w sekwencji. Moja logika wyboru widoku Utwórz / zniszcz widok była taka, że jeśli fragment nie ma widoku, nie obchodzi mnie animowanie go, aby nadal był widoczny. To podejście powinno również działać lepiej z ViewPagerami, które używają fragmentów, ponieważ nie będziesz śledzić każdego pojedynczego fragmentu, który przechowuje FragmentPagerAdapter, ale tylko 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();
}
}
Teraz, gdy wszystkie twoje fragmenty są przechowywane w pamięci przez fragment nadrzędny, możesz wywołać na nich animate w ten sposób, a twoje fragmenty podrzędne nie znikną.
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();
Poza tym, tak to masz, oto plik no_anim.xml, który znajduje się w folderze 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>
Ponownie, nie sądzę, aby to rozwiązanie było idealne, ale jest znacznie lepsze niż w przypadku każdego wystąpienia fragmentu potomnego, implementującego niestandardowy kod w fragmencie nadrzędnym, aby śledzić każde dziecko. Byłem tam i to nie jest zabawne.
R.id.fragmentHolder
w odniesieniu do A, A1, A2 itd.?