FragmentTransaction动画在顶部滑动

Mat*_*ola 68 android android-animation android-fragments

我试图使用FragmentTransaction.setCustomAnimations实现以下效果.

  1. 片段A正在显示
  2. 用碎片B替换碎片A.碎片A在更换过程中应保持可见.片段B应从右侧滑入.片段B应该在片段A的顶部滑动.

在动画设置中获取幻灯片没问题.我的问题是,我无法弄清楚如何使Fragment A停留在原来的位置,并且在动画幻灯片运行时将其置于片段B之下.无论我做什么,似乎片段A都在顶部.

我怎样才能做到这一点?

这是FragmentTransaction代码:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_right, R.anim.nothing, R.anim.nothing,
    R.anim.slide_out_right);
ft.replace(R.id.fragment_content, fragment, name);
ft.addToBackStack(name);
ft.commit();
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我已经为"out"动画定义了一个动画R.anim.nothing,因为我实际上不希望Fragment A做任何事情,只是在事务中保持原样.

以下是动画资源:

slide_in_right.xml

<translate xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_mediumAnimTime"
    android:fromXDelta="100%p"
    android:toXDelta="0"
    android:zAdjustment="top" />
Run Code Online (Sandbox Code Playgroud)

nothing.xml

<alpha xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="@android:integer/config_mediumAnimTime"
    android:fromAlpha="1.0"
    android:toAlpha="1.0"
    android:zAdjustment="bottom" />
Run Code Online (Sandbox Code Playgroud)

小智 20

我不知道你是否还需要答案,但我最近需要做同样的事情,我找到了一种方法来做你想做的事.

我做了这样的事情:

FragmentManager fm = getFragmentManager();
FragmentTransaction ft = fm.beginTransaction();

MyFragment next = getMyFragment();

ft.add(R.id.MyLayout,next);
ft.setCustomAnimations(R.anim.slide_in_right,0);
ft.show(next);
ft.commit();
Run Code Online (Sandbox Code Playgroud)

我在FrameLayout中显示我的片段.

它会罚款,但旧的Fragment仍在我的视图中,我让android管理它就像他想要的那样,因为如果我放:

ft.remove(myolderFrag);
Run Code Online (Sandbox Code Playgroud)

在动画期间不显示.

slide_in_right.xml

    <?xml version="1.0" encoding="utf-8"?> 
<set xmlns:android="http://schemas.android.com/apk/res/android" >
<translate android:duration="150" android:fromXDelta="100%p" 
android:interpolator="@android:anim/linear_interpolator"
android:toXDelta="0" />
 </set>
Run Code Online (Sandbox Code Playgroud)


小智 18

从Lollipop开始,您可以增加输入片段的de translationZ.它将出现在现有的上方.

例如:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    ViewCompat.setTranslationZ(getView(), 100.f);
}
Run Code Online (Sandbox Code Playgroud)

如果要仅在动画持续时间内修改translationZ值,则应执行以下操作:

@Override
public Animation onCreateAnimation(int transit, final boolean enter, int nextAnim) {
    Animation nextAnimation = AnimationUtils.loadAnimation(getContext(), nextAnim);
    nextAnimation.setAnimationListener(new Animation.AnimationListener() {

        private float mOldTranslationZ;

        @Override
        public void onAnimationStart(Animation animation) {
            if (getView() != null && enter) {
                mOldTranslationZ = ViewCompat.getTranslationZ(getView());
                ViewCompat.setTranslationZ(getView(), 100.f);
            }
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            if (getView() != null && enter) {
                ViewCompat.setTranslationZ(getView(), mOldTranslationZ);
            }
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }
    });
    return nextAnimation;
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,由于时间问题,降低 ned 的高度会导致一些闪烁,这意味着被替换的片段还没有完成动画。我通过稍微延迟返回高程来解决它。 (2认同)
  • 对我不起作用。它给出了 android.content.res.Resources$NotFoundException: Resource ID #0x0 错误 (2认同)

Mat*_*ola 8

我找到了一个适合我的解决方案.我最终使用了一个带有FragmentStatePagerAdapter的ViewPager.ViewPager提供了滑动行为和碎片中的FragmentStatePagerAdapter交换.实现将一个页面显示在传入页面"下"的效果的最后一个技巧是使用PageTransformer.PageTransformer会覆盖ViewPager页面之间的默认转换.下面是一个示例PageTransformer,它通过翻译实现效果,并在左侧页面上实现少量缩放.

public class ScalePageTransformer implements PageTransformer {
    private static final float SCALE_FACTOR = 0.95f;

    private final ViewPager mViewPager;

    public ScalePageTransformer(ViewPager viewPager) {
            this.mViewPager = viewPager;
    }

    @SuppressLint("NewApi")
    @Override
    public void transformPage(View page, float position) {
        if (position <= 0) {
            // apply zoom effect and offset translation only for pages to
            // the left
            final float transformValue = Math.abs(Math.abs(position) - 1) * (1.0f - SCALE_FACTOR) + SCALE_FACTOR;
            int pageWidth = mViewPager.getWidth();
            final float translateValue = position * -pageWidth;
            page.setScaleX(transformValue);
            page.setScaleY(transformValue);
            if (translateValue > -pageWidth) {
                page.setTranslationX(translateValue);
            } else {
                page.setTranslationX(0);
            }
        }
    }

}
Run Code Online (Sandbox Code Playgroud)


Mer*_*erk 5

经过更多的实验(因此这是我的第二个答案),问题似乎是R.anim.nothing意味着"消失",当我们想要另一个明确表示"留下来"的动画时.解决方案是定义一个真正的"无所事事"动画,如下所示:

制作文件no_animation.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <scale
        android:interpolator="@android:anim/linear_interpolator"
        android:fromXScale="1.0"
        android:toXScale="1.0"
        android:fromYScale="1.0"
        android:toYScale="1.0"
        android:duration="200"
        />
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:fromAlpha="1.0"
        android:toAlpha="0.0"
        android:duration="200"
        android:startOffset="200"
        />
</set>
Run Code Online (Sandbox Code Playgroud)

现在只需按照您的意愿行事:

getActivity().getSupportFragmentManager().beginTransaction()
                .setCustomAnimations(R.anim.slide_in_right, R.anim.no_animation)
                .replace(R.id.container, inFrag, FRAGMENT_TAG)
                .addToBackStack("Some text")
                .commit();
Run Code Online (Sandbox Code Playgroud)

  • 很好的想法,但这不起作用,因为交易立即删除片段,我可以看到动画期间第二个片段下面的白色屏幕. (2认同)