Android Fragments和动画

你应该如何实现这种滑动,例如蜂窝Gmail客户端使用?

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

256536 次浏览

为了使片段之间的转换动画化,或者使显示或隐藏片段的过程动画化,可以使用Fragment Manager来创建Fragment Transaction

在每个Fragment Transaction中,你可以分别指定用于显示和隐藏的in和out动画(或者当使用replace时两者都指定)。

下面的代码展示了如何通过滑动出一个片段并滑动另一个片段来替换一个片段。

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>

如果你不需要使用支持库,那么可以看看罗马的 answer。

但是如果你想使用支持库,你必须使用下面描述的旧动画框架。

在咨询里特•的blindstuff的的答案后,我已经得到了以下代码的工作。

当back被按下时,片段出现从右边滑进来向左滑去

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

顺序很重要。这意味着你必须在__ABC1之前调用setCustomAnimations(),否则动画将不会生效!< / em >

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

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或任何其他数字。

请注意,如果在片段替换之间发生了配置更改(例如旋转),反向操作不会动画化。这是一个记录错误,仍然存在于支持库的rev 20中。

我修改过的支持库支持使用视图动画(即<translate>, <rotate>)和对象动画器(即<objectAnimator>)进行片段过渡。它是用NineOldAndroids实现的。详细信息请参考我在github上的文档。

我用下面的方法解决这个问题

Animation anim = AnimationUtils.loadAnimation(this, R.anim.slide);
fg.startAnimation(anim);
this.fg.setVisibility(View.VISIBLE); //fg is a View object indicate fragment

我强烈建议你使用这个而不是创建动画文件,因为这是一个更好的解决方案。Android Studio已经提供了默认的 animation,你可以在不创建任何新的XML文件的情况下使用。动画的名字是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();

输出:

enter image description here

对我来说,我需要视图方向:

In ->从右滑动

Out ->向左滑动

下面是我的代码:

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