下面是这个场景: Activity包含片段A,它使用getChildFragmentManager()在其onCreate中添加片段A1和A2,如下所示:
getChildFragmentManager()
.beginTransaction()
.replace(R.id.fragmentOneHolder, new FragmentA1())
.replace(R.id.fragmentTwoHolder, new FragmentA2())
.commit()到目前为止,一切都很好,一切都在按预期运行。
然后,我们在活动中运行以下事务:
getSupportFragmentManager()
.beginTransaction()
.setCustomAnimations(anim1, anim2, anim1, anim2)
.replace(R.id.fragmentHolder, new FragmentB())
.addToBackStack(null)
.commit()在转换过程中,fragment B的enter动画可以正确运行,但fragment A1和A2会完全消失在中。当我们使用Back按钮恢复事务时,它们将正确初始化,并在popEnter动画期间正常显示。
在我的简短测试中,它变得更加奇怪-如果我设置子片段的动画(见下文),当我们添加片段B时,exit动画会间歇性地运行
getChildFragmentManager()
.beginTransaction()
.setCustomAnimations(enter, exit)
.replace(R.id.fragmentOneHolder, new FragmentA1())
.replace(R.id.fragmentTwoHolder, new FragmentA2())
.commit()我想要实现的效果很简单--我想要exit (或者它应该是popExit?)要运行的fragment A (anim2)上的动画,为整个容器(包括其嵌套子容器)设置动画。
有什么方法可以做到这一点吗?
编辑:请查找测试用例here
Edit2:感谢@StevenByle推动我继续尝试静态动画。显然,您可以在每个操作的基础上设置动画(而不是整个事务的全局动画),这意味着子级可以有一个不确定的静态动画集,而它们的父级可以有一个不同的动画,整个事情可以在一个事务中提交。请参阅下面的讨论和updated test case project。
发布于 2013-02-22 13:53:28
为了避免用户在事务中删除/替换父片段时看到嵌套片段消失,您可以通过提供这些片段的图像来“模拟”这些片段仍然存在,因为它们出现在屏幕上。此图像将用作嵌套片段容器的背景,因此即使嵌套片段的视图消失,图像也会模拟它们的存在。此外,我不认为失去与嵌套片段的视图的交互性是一个问题,因为我认为您不会希望用户在它们刚刚被移除的过程中对它们采取行动(可能也是作为一个用户操作)。
我已经做了一个设置背景图像的little example (一些基本的东西)。
发布于 2014-04-25 01:44:50
因此,似乎有很多不同的解决方法,但基于@Jayd16的回答,我认为我已经找到了一个相当可靠的通用解决方案,它仍然允许对子片段进行自定义过渡动画,并且不需要对布局进行位图缓存。
创建一个扩展Fragment的BaseFragment类,并使您的所有片段都扩展该类(不仅仅是子片段)。
在BaseFragment类中,添加以下内容:
// Arbitrary value; set it to some reasonable default
private static final int DEFAULT_CHILD_ANIMATION_DURATION = 250;
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
final Fragment parent = getParentFragment();
// Apply the workaround only if this is a child fragment, and the parent
// is being removed.
if (!enter && parent != null && parent.isRemoving()) {
// This is a workaround for the bug where child fragments disappear when
// the parent is removed (as all children are first removed from the parent)
// See https://code.google.com/p/android/issues/detail?id=55228
Animation doNothingAnim = new AlphaAnimation(1, 1);
doNothingAnim.setDuration(getNextAnimationDuration(parent, DEFAULT_CHILD_ANIMATION_DURATION));
return doNothingAnim;
} else {
return super.onCreateAnimation(transit, enter, nextAnim);
}
}
private static long getNextAnimationDuration(Fragment fragment, long defValue) {
try {
// Attempt to get the resource ID of the next animation that
// will be applied to the given fragment.
Field nextAnimField = Fragment.class.getDeclaredField("mNextAnim");
nextAnimField.setAccessible(true);
int nextAnimResource = nextAnimField.getInt(fragment);
Animation nextAnim = AnimationUtils.loadAnimation(fragment.getActivity(), nextAnimResource);
// ...and if it can be loaded, return that animation's duration
return (nextAnim == null) ? defValue : nextAnim.getDuration();
} catch (NoSuchFieldException|IllegalAccessException|Resources.NotFoundException ex) {
Log.w(TAG, "Unable to load next animation from parent.", ex);
return defValue;
}
}不幸的是,它确实需要反射;但是,由于此变通方法是针对支持库的,所以除非更新支持库,否则不会有底层实现更改的风险。如果你是从源代码构建支持库,你可以为下一个动画资源ID添加一个访问器到Fragment.java,并删除对反射的需要。
这个解决方案不需要“猜测”父对象的动画持续时间(这样“什么都不做”动画的持续时间将与父对象的退出动画的持续时间相同),并且允许您仍然对子片段执行自定义动画(例如,如果您正在使用不同的动画交换子片段)。
发布于 2014-03-27 05:54:38
我想出了一个相当干净的解决方案。IMO是最不麻烦的,虽然从技术上讲这是“绘制位图”的解决方案,但至少它是由片段库抽象出来的。
确保你的子片段用下面的代码覆盖了父类:
private static final Animation dummyAnimation = new AlphaAnimation(1,1);
static{
dummyAnimation.setDuration(500);
}
@Override
public Animation onCreateAnimation(int transit, boolean enter, int nextAnim) {
if(!enter && getParentFragment() != null){
return dummyAnimation;
}
return super.onCreateAnimation(transit, enter, nextAnim);
}如果我们在子frags上有一个退出动画,它们将被动画而不是闪烁。我们可以通过一个动画来利用这一点,该动画只需在一段时间内以完整的alpha绘制子片段。这样,它们将在父片段动画中保持可见,从而提供所需的行为。
我能想到的唯一问题就是跟踪这个持续时间。我也许可以将它设置为一个较大的数字,但我担心如果它仍然在某个地方绘制该动画,可能会出现性能问题。
https://stackoverflow.com/questions/14900738
复制相似问题