动画片段之间的过渡

Lab*_*lan 273 android android-3.0-honeycomb

我试图动画片段之间的过渡.我从以下Android片段和动画中得到了答案

FragmentTransaction ft = getFragmentManager().beginTransaction();
ft.setCustomAnimations(R.anim.slide_in_left, R.anim.slide_out_right);

DetailsFragment newFragment = DetailsFragment.newInstance();

ft.replace(R.id.details_fragment_container, newFragment, "detailFragment");

// Start the animated transition.
ft.commit();
Run Code Online (Sandbox Code Playgroud)

还有我的R.anim.slide_in_left

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="50%p" android:toXDelta="0"
            android:duration="@android:integer/config_mediumAnimTime"/>
       <alpha android:fromAlpha="0.0" android:toAlpha="1.0"
            android:duration="@android:integer/config_mediumAnimTime" />
</set>
Run Code Online (Sandbox Code Playgroud)

但当我尝试这个时,它表明了

02-08 16:27:37.961: ERROR/AndroidRuntime(1717): FATAL EXCEPTION: main
02-08 16:27:37.961: ERROR/AndroidRuntime(1717): java.lang.RuntimeException: Unknown animator name: translate
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:129)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:126)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.createAnimatorFromXml(AnimatorInflater.java:93)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.animation.AnimatorInflater.loadAnimator(AnimatorInflater.java:72)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.loadAnimator(FragmentManager.java:621)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:733)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.moveToState(FragmentManager.java:919)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.BackStackRecord.run(BackStackRecord.java:578)
02-08 16:27:37.961: ERROR/AndroidRuntime(1717):     at android.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1217)
Run Code Online (Sandbox Code Playgroud)

有任何想法吗?当我检查Honeycomb API参考时translate就在那里.我错过了什么?
有没有其他方法来动画片段之间的过渡?谢谢

Rom*_*rik 341

您需要使用新的android.animation与框架(对象动画)FragmentTransaction.setCustomAnimations,以及FragmentTransaction.setTransition.

以下是使用setCustomAnimationsApiDemos的FragmentHideShow.java的示例:

ft.setCustomAnimations(android.R.animator.fade_in, android.R.animator.fade_out);
Run Code Online (Sandbox Code Playgroud)

这是来自res/animator/fade_in.xml的相关动画XML :

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:interpolator/accelerate_quad"
    android:valueFrom="0"
    android:valueTo="1"
    android:propertyName="alpha"
    android:duration="@android:integer/config_mediumAnimTime" />
Run Code Online (Sandbox Code Playgroud)

请注意,您可以将多个动画师组合使用<set>,就像使用旧动画框架一样.


编辑:由于人们询问插入/滑出,我会在这里评论.

滑入式滑出

当然,你可以动画translationX,translationY,x,和y性质,但一般涉及幻灯片动画内容,并从屏幕外.据我所知,没有任何使用相对值的过渡属性.但是,这并不妨碍您自己编写它们.请记住,属性动画只需要对您正在动画的对象(在本例中为视图)中使用getter和setter方法,因此您可以在视图子类上创建自己的 方法getXFractionsetXFraction方法,如下所示:

public class MyFrameLayout extends FrameLayout {
    ...
    public float getXFraction() {
        return getX() / getWidth(); // TODO: guard divide-by-zero
    }

    public void setXFraction(float xFraction) {
        // TODO: cache width
        final int width = getWidth();
        setX((width > 0) ? (xFraction * width) : -9999);
    }
    ...
}
Run Code Online (Sandbox Code Playgroud)

现在您可以为'xFraction'属性设置动画,如下所示:

res/animator/slide_in.xml:

<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:interpolator="@android:anim/linear_interpolator"
    android:valueFrom="-1.0"
    android:valueTo="0"
    android:propertyName="xFraction"
    android:duration="@android:integer/config_mediumAnimTime" />
Run Code Online (Sandbox Code Playgroud)

请注意,如果您要设置动画的对象与其父对象的宽度不同,则事情看起来不太合适,因此您可能需要调整属性实现以适合您的用例.

  • 实际上,罗马,建议应该反过来:当使用支持库时,你需要使用旧的动画框架(android.R.anim)与FragmentTransaction.setCustomAnimations ao (13认同)
  • 我让fade_in和fade_out工作,但是/ res/animator中的其他人给出了错误.而且这些似乎都不是为了滑入和滑出.我已经尝试编写自己的xml来做到这一点,但我最终得到的只是片段之上的片段.还有一些帮助吗? (8认同)
  • 我得到11-19 10:27:50.912:W/PropertyValuesHolder(23107):在目标类类android.widget.FrameLayout上找不到类型为float的方法setXFraction().但在我的XML中,我有自定义视图MyFrameLayout.有任何想法吗? (6认同)

Hir*_*tel 172

我这样做了:

添加此方法以使用动画替换片段:

public void replaceFragmentWithAnimation(android.support.v4.app.Fragment fragment, String tag){
    FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
    transaction.setCustomAnimations(R.anim.enter_from_left, R.anim.exit_to_right, R.anim.enter_from_right, R.anim.exit_to_left);
    transaction.replace(R.id.fragment_container, fragment);
    transaction.addToBackStack(tag);
    transaction.commit();
}
Run Code Online (Sandbox Code Playgroud)

您必须在与资源关联的anim文件夹中添加 四个动画:

enter_from_left.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="-100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>
Run Code Online (Sandbox Code Playgroud)

exit_to_right.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>
Run Code Online (Sandbox Code Playgroud)

enter_from_right.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="100%" android:toXDelta="0%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700" />
</set>
Run Code Online (Sandbox Code Playgroud)

exit_to_left.xml:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:shareInterpolator="false">
    <translate
        android:fromXDelta="0%" android:toXDelta="-100%"
        android:fromYDelta="0%" android:toYDelta="0%"
        android:duration="700"/>
</set>
Run Code Online (Sandbox Code Playgroud)

输出:

在此输入图像描述

完成了.

  • 好的解决方案 但是我不确定你为什么要把方向换成RTL.我的方法:`.setCustomAnimations(R.anim.enter_from_right,R.anim.exit_to_left,R.anim.enter_from_left,R.anim.exit_to_right)` (13认同)
  • 大声笑,我回来了解决方案.我在每个java类上导入android.app.fragment和FragmentManager.在检查了一些材料之后,我发现使用'setCustomAnimations()'需要导入android.support.v4库.重要的是,应该是'support.v4.app'!我用'getSupportFragmentManager()'替换了所有方法'getFragmentManager()',并将所有导入'android.app.Fragment/FragmentManager ...'替换为'android.support.v4.app ....',然后这个动画开始运作良好而不会崩溃...如果你们遇到类似的情况,请阅读我的解决方案.Thx Hiren Patel xD (3认同)
  • 很棒的解决方案.类似的方法和相同的动画文件适用于活动之间的转换. (2认同)
  • 感谢Hiren,我将速度(700)更改为(300)更好,更像iOS (2认同)

sco*_*awg 51

如果你有能力将自己绑在Lollipop之后,那么这似乎可以解决问题:

import android.transition.Slide;
import android.util.Log;
import android.view.Gravity;
.
.
.
f = new MyFragment();
f.setEnterTransition(new Slide(Gravity.RIGHT));
f.setExitTransition(new Slide(Gravity.LEFT));
getFragmentManager()
    .beginTransaction()
    .replace(R.id.content, f, FRAG_TAG)  // FRAG_TAG is the tag for your fragment
    .commit();
Run Code Online (Sandbox Code Playgroud)

希望这可以帮助.

  • @EranGoldin没有什么是永恒的......你今天会嘲笑Android 2.0+唯一的解决方案吗? (12认同)

str*_*uck 47

Nurik的回答非常有帮助,但在找到这个之前我无法让它工作.简而言之,如果您使用兼容性库(例如SupportFragmentManager而不是FragmentManager),则XML动画文件的语法将有所不同.


kir*_*ilv 27

这是片段之间的幻灯片放入/缩小动画:

FragmentTransaction transaction = getFragmentManager().beginTransaction();
transaction.setCustomAnimations(R.animator.enter_anim, R.animator.exit_anim);
transaction.replace(R.id.listFragment, new YourFragment());
transaction.commit();
Run Code Online (Sandbox Code Playgroud)

我们正在使用objectAnimator.

以下是animator子文件夹中的两个xml文件.

enter_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
     <objectAnimator
         xmlns:android="http://schemas.android.com/apk/res/android"
         android:duration="1000"
         android:propertyName="x"
         android:valueFrom="2000"
         android:valueTo="0"
         android:valueType="floatType" />
</set>
Run Code Online (Sandbox Code Playgroud)

exit_anim.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
    <objectAnimator
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:propertyName="x"
        android:valueFrom="0"
        android:valueTo="-2000"
        android:valueType="floatType" />
</set>
Run Code Online (Sandbox Code Playgroud)

我希望这会对某人有所帮助.

  • 移动视图2000 px,是一个非常难看的解决方案. (36认同)
  • exit_anim只为我弹出"弹出"屏幕,它不会在屏幕上显示动画.有任何想法吗?我正在使用`.setCustomAnimations(R.animator.slide_in_left,R.animator.slide_out_right,R.animator.slide_in_left,R.animator.slide_out_right) (4认同)

Cha*_*lie 22

对于被捕获的任何其他人,请确保在构建事务时调用replace/add之前调用setCustomAnimations.


she*_*pya 12

FragmentTransaction的Android SDK实现想要一段Animator时间支持库想要一个Animation,不要问我为什么但是在missluk的评论之后我调查了android 4.0.3代码和支持库.Android SDK使用loadAnimator()并支持库使用loadAnimation()


Gow*_*n M 5

尝试使用这种简单而快速的解决方案。Android提供了一些default animation

fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
Run Code Online (Sandbox Code Playgroud)
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left, android.R.anim.slide_out_right);
fragmentManager.addOnBackStackChangedListener(this);
fragmentTransaction.replace(R.id.frame, firstFragment, "h");
fragmentTransaction.addToBackStack("h");
fragmentTransaction.commit();
Run Code Online (Sandbox Code Playgroud)

输出:

在此处输入图片说明