编辑:
我最终取消了此解决方案,因为它存在其他问题。Square最近推出了两个替代片段的库。我认为这可能比尝试将片段强制执行不想要的操作更好。
http://corner.squareup.com/2014/01/mortar-and-flow.html
@@@@@@@@@@@@@@@@@@@@@@@@@@@@
我想提供这个解决方案,以帮助未来遇到这个问题的人们。如果您跟踪原始帖子者与其他人的对话,并查看他发布的代码,您会发现原始帖子者最终得出结论:在动画父片段时,在子片段上使用无操作动画。这个解决方案并不理想,因为它强制您跟踪所有子片段,当使用具有FragmentPagerAdapter的ViewPager时,这可能很麻烦。
由于我在许多地方都使用子片段,因此我想出了这个高效且模块化的解决方案(因此可以轻松删除),以防止他们修复它并且不再需要此无操作动画。
您可以以许多方式实现此功能。我选择使用单例,并将其称为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;
}
}
接下来,您需要有一个扩展Fragment的类,所有的Fragment(至少是子Fragment)都要继承它。我已经有了这个类,并称其为BaseFragment。当一个Fragment的视图被创建时,我们将其添加到ChildFragmentAnimationManager中,在其被销毁时将其删除。您可以在onAttach/onDetach或其他匹配方法中完成此操作。我选择使用Create/Destroy View的逻辑是因为如果一个Fragment没有视图,我不关心是否对其进行动画处理以保持可见。这种方法也应该更好地与使用Fragment作为ViewPager的组件一起使用,因为您无需跟踪FragmentPagerAdapter正在持有的每个单独的Fragment,而只需要跟踪三个即可。
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
是什么? - CommonsWarechangeFragment
方法一次吗? - userchangeFragment
方法中的事务将有两个操作,一个是隐藏FragmentA
,另一个是将FragmentB
添加到容器中。这应该适用于退出和进入动画。 - user