我独处时最轻松,因为我不觉得自己乏味,即使乏味,也自己承受,不累及他人,无需感到不安。 —— 周国平《风中的纸屑》
Android Fragment切换动画(注意返回键和虚拟返回键切换的问题)
实际效果图:
Fragment切换动画主要使用FragmentTransaction事务类中的setCustomAnimations()方法:
参数说明:
enter
:指的是当一个Fragment
被添加或者绑定到视图上时,该Fragment
进入视图时的动画效果;
exit
: 指的是当一个Fragment
从视图上被移除或者解除绑定时,该Fragment
移除视图时的动画效果;
popEnter
:指的是当调用popBackStack()
或者类似的方法将栈顶的Fragment
弹出后,Fragment
栈的栈顶Fragment
被重新添加或者重新绑定到视图上时,该Fragment进去视图的动画效果;
popExit
:指的是当调用popBackStack()
或者类似的方法将栈顶的Fragment
弹出时,被弹出的Fragment
从视图中被移除或者解除绑定的动画效果。
动画效果(为了看清,进入退出的动画时间不同,具体用的时候设置成需要的):
① 当在MainFragment
中点击搜索按钮切换到SearchFragment
时,MainFragment
要被移除所以执行的是exit
,对应fragment_exit.xml
动画,而SearchFragment
要添加进入进来所以执行的是enter
,对应fragment_enter.xml
动画;
② 当在SearchFragment
中点击返回按钮切换到MainFragment
时,执行popBackStack()
方法,SearchFragment
被弹出,弹出后MainFragment
进入栈顶,所以SearchFragment
执行的是popExit
,对应fragment_pop_exit.xml
动画,而MainFragment
执行的是popEnter
,对应fragment_pop_enter.xml
动画
创建步骤:
Ⅰ.在res
文件下创建anim
文件夹
Ⅱ.创建四个动画资源文件
① Fragment
进入 enter
fragment_enter.xml
<?xml version="1.0" encoding="utf-8"?>
<!- 从父布局最右边进入直到完全充满父布局,动画时间1秒 -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true"
>
<translate
android:fromXDelta="100%p"
android:toXDelta="0" />
</set>
效果:
② Fragment
移除 exit
fragment_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 从父布局最左边向左平移直到完全移出父布局,动画时间4秒 -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="4000"
android:fillAfter="true">
<translate
android:fromXDelta="0"
android:toXDelta="-100%p"
/>
</set>
③ 从右边进入 popEnter
fragment_pop_enter.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 从离父布局最左边一个父布局宽度开始向右平移一个父布局的宽度 , 动画时间4秒-->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="4000">
<translate
android:fromXDelta="-100%p"
android:toXDelta="0"
/>
</set>
④ 从右边出去 popExit
fragment_pop_exit.xml
<?xml version="1.0" encoding="utf-8"?>
<!-- 从左往右移动一个父布局的宽度,动画时间0.3秒 -->
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:fillAfter="true"
android:duration="300">
<translate
android:fromXDelta="0"
android:toXDelta="100%p"/>
</set>
Ⅲ. Java
代码,
import androidx.fragment.app.Fragment;
MainFragment.java
部分代码:
bt_search.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 跳转到 SearchFragment
replaceFragment(new SearchFragment());
}
});
/**
* 替换Fragment
* @param fragment 替换的Fragment
*/
public void replaceFragment(Fragment fragment){
FragmentManager manager = getActivity().getSupportFragmentManager();
FragmentTransaction transaction = manager.beginTransaction();
// 切换Fragment时执行的动画
transaction.setCustomAnimations(
R.anim.fragment_enter,
R.anim.fragment_exit,
R.anim.fragment_pop_enter,
R.anim.fragment_pop_exit);
// R.id.fragment_container 是 activity_main.xml中 盛装 Fragment的容器
transaction.add(R.id.fragment_container, fragment);
// 添加到返回栈中
transaction.addToBackStack(null);
transaction.hide(this);
transaction.commit();
}
SearchFragment.java
部分
bt_back.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// 返回到 MainFragment
// 要用这个方法去弹出栈顶Fragment,返回键才能和虚拟返回键执行一样的动画
getActivity().getSupportFragmentManager().popBackStack();
}
});