当前位置: 首页 > 知识库问答 >
问题:

嵌套片段在过渡动画期间消失

岳意蕴
2023-03-14

这是一个场景:活动包含片段A,它反过来使用getChildFragmentManager()在其onCreate中添加片段A1A2像这样:

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()

在转换过程中,片段B的enter动画运行正常,但片段A1和A2完全消失。当我们使用后退按钮还原事务时,它们会正确初始化,并在弹出键动画期间正常显示。

在我的简短测试中,情况变得更奇怪了——如果我为子片段设置动画(见下文),当我们添加片段时,退出动画会断断续续地运行

getChildFragmentManager()
  .beginTransaction()
  .setCustomAnimations(enter, exit)
  .replace(R.id.fragmentOneHolder, new FragmentA1())
  .replace(R.id.fragmentTwoHolder, new FragmentA2())
  .commit()

我想要实现的效果很简单-我想要退出(或者应该是popExit?)在片段A上的动画(动画2)运行,动画整个容器,包括它的嵌套子容器。

有什么方法可以做到这一点吗?

编辑:请在此处查找测试用例

编辑2:感谢@StevenByle让我继续尝试静态动画。显然,您可以基于每个操作设置动画(不是整个事务的全局),这意味着子级可以有一个不确定的静态动画集,而其父级可以有不同的动画,并且整个事务可以在一个事务中提交。请参阅下面的讨论和更新的测试用例项目。

共有3个答案

殳智志
2023-03-14

我想出了一个非常干净的解决方案。在我看来,这是最简单的黑客行为,虽然从技术上讲这是“绘制位图”的解决方案,但至少它是由片段库抽象出来的。

确保您的子frags使用以下内容重写父类:

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);
}

如果我们对子片段有退出动画,它们将被动画化而不是眨眼。我们可以通过使用一个动画来利用这一点,该动画只需在一段时间内以完全alpha绘制子片段。这样,当父片段动画时,它们将在父片段中保持可见,从而提供所需的行为。

我能想到的唯一问题就是跟踪这段时间。我可能会将其设置为一个较大的数字,但我担心如果它仍在某处绘制动画,可能会有性能问题。

锺离霖
2023-03-14

为了避免用户在事务中移除/替换父片段时看到嵌套片段消失,您可以通过提供屏幕上显示的片段图像来“模拟”仍然存在的那些片段。此图像将用作嵌套片段容器的背景,因此即使嵌套片段的视图消失,图像也将模拟其存在。此外,我不认为失去与嵌套片段视图的交互性是一个问题,因为我认为您不希望用户在删除它们的过程中对它们进行操作(可能也是一种用户操作)。

我已经用设置背景图像(一些基本的东西)做了一个小例子。

傅雪松
2023-03-14

因此,似乎有很多不同的解决方法,但根据@Jayd16的回答,我认为我找到了一个非常可靠的全面解决方案,它仍然允许在子片段上自定义过渡动画,并且不需要对布局进行位图缓存。

拥有一个扩展片段的类,并使所有片段扩展该类(而不仅仅是子片段)。

在该类中,添加以下内容:

// 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的访问器。java,无需反射。

此解决方案消除了“猜测”父级动画持续时间的需要(因此“什么都不做”动画将具有与父级退出动画相同的持续时间),并允许您仍然对子片段执行自定义动画(例如,如果您使用不同的动画交换子片段)。

 类似资料:
  • 我见过很多人用子片段描述这种情况(例如),但我没有使用子片段。当我向事务添加动画时,退出的片段会立即消失,而进入的片段会以预期的enter动画进入。当我按下后,同样的事情发生了。。。退出的片段立即消失,原始片段以适当的弹出式输入动画进入。 我做错了什么? 我在一个实现PreferenceFragmentCompat的AppCompatActivity中这样做。在PreferenceStartFra

  • 主要内容:过渡,实例,实例,实例,实例,JavaScript 钩子,HTML 代码:,JavaScript 代码:,实例,初始渲染的过渡本章节我们主要讨论 Vue.js 的过渡效果与动画效果。 过渡 Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果。 Vue 提供了内置的过渡封装组件,该组件用于包裹要实现过渡效果的组件。 语法格式 我们可以通过以下实例来理解 Vue 的过渡是如何实现的: 实例 <div id = "databinding"> <button v-on:c

  • 问题内容: 因此,我了解了如何同时执行CSS3过渡和动画。我用谷歌搜索的不清楚是什么时候使用它。 例如,如果我想使球弹跳,很明显,动画是必经之路。我可以提供关键帧,而浏览器将做中间帧,并且我将获得一个不错的动画。 然而,在某些情况下,无论哪种方式都可以达到上述效果。一个简单而常见的示例是实现Facebook风格的滑动抽屉菜单: 可以通过以下过渡来实现此效果: 或者,通过类似这样的动画: 使用HTM

  • 内置过渡动画 Element 内应用在部分组件的过渡动画,你也可以直接使用。在使用之前请阅读 transition 组件文档 。 fade 淡入淡出 提供 el-fade-in-linear 和 el-fade-in 两种效果。 <template> <div> <el-button @click="show = !show">Click Me</el-button> <di

  • 定义 基于animejs封装的React组件。 图片展示 代码演示 import Anime from 'pile/dist/components/anime' const {CssTransform} = Anime let moveAlone = { targets: '.anime-move-demo-alone', left: '240px', backgroundColo

  • Element Plus 内应用在部分组件的过渡动画,你也可以直接使用。在使用之前请阅读 transition 组件文档 。 fade 淡入淡出 提供 el-fade-in-linear 和 el-fade-in 两种效果。 <template> <div> <el-button @click="show = !show">Click Me</el-button> <div