@@@@@@@@@@@@@@@@@@@@@@@@@@@
EDIT: Я вирішив не виконати це рішення, оскільки виникли інші проблеми. Нещодавно на площі вийшли 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 і видаляємо його, коли він знищується. Ви можете зробити це onAttach / Detach або інші методи узгодження у послідовності. Моя логіка вибору «Створити / знищити перегляд» полягала в тому, що якщо у фрагмента немає перегляду, я не переймаюся анімацією, щоб продовжувати його бачити. Цей підхід також повинен краще працювати з ViewPagers, який використовує фрагменти, оскільки ви не будете відслідковувати кожен окремий фрагмент, який утримує 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();
}
}
Тепер, коли всі ваші фрагменти зберігаються в пам’яті батьківським фрагментом, ви можете викликати анімацію на них так, і ваші дочірні фрагменти не зникнуть.
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 тощо?