Android片段和动画


265

您应该如何实现例如Honeycomb Gmail客户端使用的那种滑动方式?

可以TransactionManager通过添加和删除片段来自动处理此问题,由于模拟器是幻灯片演示,因此很难测试:)

Answers:


388

要为片段之间的过渡设置动画,或者为显示或隐藏片段的动画设置动画,请使用Fragment Manager来创建Fragment Transaction

在每个“片段事务”中,您可以指定将分别用于显示和隐藏(或在使用替换时均用于显示和隐藏)的入和出动画。

以下代码显示了如何通过滑出一个片段并在其位置滑动另一个片段来替换片段。

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

要通过隐藏或显示片段来实现相同的目的,您只需调用ft.showft.hide,分别传入您希望显示或隐藏的片段。

作为参考,XML动画定义将使用objectAnimator标签。slide_in_left的示例可能看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<set>
  <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="x" 
    android:valueType="floatType"
    android:valueFrom="-1280"
    android:valueTo="0" 
    android:duration="500"/>
</set>

57
当我尝试这样做时,它显示RuntimeException:未知的动画师名称:translate
Labeeb Panampullan

3
确保使用一组objectAnimator定义而不是旧的动画定义来构造slide_in_left和right中定义的动画。
Reto Meier

7
这很有帮助。我走在正确的轨道上,但并没有一路走到那里。对于其他读者,您还可以将android:interpolator作为属性,并指定自己喜欢的属性(例如“ @android:interpolator / linear”)。默认为“ @android:interpolator / accelerate_decelerate”。
Dave MacLean

6
我的目标是使用兼容API达到API级别7。我有办法为“片段”制作动画吗?
Jarrod Smith

5
@JarrodSmith,您可以尝试使用NineOldAndroids之类的兼容性库将Honeycomb API引入Eclair。
S先生

249

如果您不必使用支持库,请查看Roman的答案。

但是如果您想使用支持库,则必须使用旧的动画框架,如下所述。

在咨询RetoBlindstuff的答案之后,我得到了以下代码。

该片段出现在从右侧滑动,并滑出向左按下时回来。

FragmentManager fragmentManager = getSupportFragmentManager();

FragmentTransaction transaction = fragmentManager.beginTransaction();
transaction.setCustomAnimations(R.anim.enter, R.anim.exit, R.anim.pop_enter, R.anim.pop_exit);

CustomFragment newCustomFragment = CustomFragment.newInstance();
transaction.replace(R.id.fragment_container, newCustomFragment );
transaction.addToBackStack(null);
transaction.commit();

顺序很重要。这意味着您必须先致电setCustomAnimations()replace()否则动画将不会生效!

接下来,这些文件必须放置在res / anim文件夹中。

enter.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

exit.xml

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="-100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_enter.xml

<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="-100%"
               android:toXDelta="0"
               android:interpolator="@android:anim/decelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

pop_exit.xml

<?xml version="1.0" encoding="utf-8"?>
<set>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
               android:fromXDelta="0"
               android:toXDelta="100%"
               android:interpolator="@android:anim/accelerate_interpolator"
               android:duration="@android:integer/config_mediumAnimTime"/>
</set>

动画的持续时间可以更改为任何默认值,例如@android:integer/config_shortAnimTime或任何其他数字。

请注意,如果在片段替换之间发生配置更改(例如旋转),则不会对后退动作进行动画处理。这是一个已记录的错误,该错误仍存在于支持库的版本20中。


47
这救了我。注意,注意顺序很重要,这自然是我第一次错过。这意味着您必须在replace()之前调用setCustomAnimations()。
Stephen Kidon

3
我尝试在片段上实现。我写了您提到的所有内容,但logcat表示:unknow动画师名称翻译如何解决此问题?顺便说一句,我在导航抽屉(滑动菜单)上称呼我的片段
Zafer Celaloglu 2014年

效果很好,但事实证明,使用构建工具21.1进行构建会产生一个错误,提示“无效的文件名:必须仅包含小写字母和数字([a-z0-9_。])”。我建议在pop_enter.xml和pop_exit.xml的答案中编辑文件名。
smichak

很棒的解决方案,当我按下后退按钮时,效果很好。我只有一个问题:如果要创建自定义的backButton,应该调用什么代码来复制后退按钮的行为?
Thomas Teilmann'3

1
托马斯(Thomas)如果想退回,则应实施以下表格:.setCustomAnimations(R.anim.pop_enter,R.anim.pop_exit,R.anim.enter,R.anim.exit)
Alex Zaraos

26

我强烈建议您使用此方法而不是创建动画文件,因为它是更好的解决方案。Android Studio已经提供了无需创建任何新XML文件即可使用的默认设置 animation。动画的名称为android.R.anim.slide_in_leftandroid.R.anim.slide_out_right,您可以按以下方式使用它们:

fragmentTransaction.setCustomAnimations(android.R.anim.slide_in_left,android.R.anim.slide_out_right);

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

输出:

在此处输入图片说明


1
android.R ...“ Android Studio提供默认动画”,不适用于android studio,它也可以在eclipse中使用,android.R是android特定的。而且,您没有共享该api具有的信息。因为android.R上的内容在不同的api上有所不同。
史蒂夫·莫雷兹

@stevemoretz thaxs bro,我同意你的观点。.我将纠正并更新我的答案...
Gowthaman M

5

我修改后的支持库支持同时使用View动画(即<translate>, <rotate>)和Object Animators(即<objectAnimator>)进行片段过渡。它由NineOldAndroids实现。有关详细信息,请参阅我在github上的文档。


2

对于我来说,我需要视图处理:

在->从右滑动

向外->向左滑动

这里为我工作的代码:

slide_in_right.xml

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

slide_out_left.xml

 <set xmlns:android="http://schemas.android.com/apk/res/android">
        <translate android:fromXDelta="0" android:toXDelta="-50%p"
                android:duration="@android:integer/config_mediumAnimTime"/>
        <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
                android:duration="@android:integer/config_mediumAnimTime" />
    </set>

交易代码:

inline fun FragmentActivity.setContentFragment(
        containerViewId: Int,
        backStack: Boolean = false,
        isAnimate: Boolean = false,
        f: () -> Fragment

): Fragment? {
    val manager = supportFragmentManager
    return f().apply {
        manager.beginTransaction().let {
            if (isAnimate)
                it.setCustomAnimations(R.anim.slide_in_right, R.anim.slide_out_left)

            if (backStack) {
                it.replace(containerViewId, this, "Fr").addToBackStack("Fr").commit()
            } else {
                it.replace(containerViewId, this, "Fr").commit()
            }
        }
    }
}

安卓似乎闪烁的过渡与动画(专门的翻译的)
加布里埃尔,德奥利维拉Rohden

@GabrielDeOliveiraRohden就我而言,并不是所有情况都如此
Serg Burlaka '19

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.