Android日常开发 - Fragment切换动画的实现

本文详细介绍了在Android应用开发中如何实现Fragment的切换,包括使用`add`和`replace`方法,以及如何设置动画效果。通过示例代码展示了如何创建进入和退出动画,并提供了实际运行的效果。同时,文章指出在使用`add`方法时,动画可能不会执行,而`replace`方法则会导致旧Fragment被移除并执行动画。最后,提到了相关博客资源供进一步学习。

Android日常开发 - Fragment切换动画的实现

在日常工作中,经常会遇到某个功能的使用引导开发。引导中的多个步骤对应多个Fragment,完成一个步骤就跳转到下一个步骤,跳转的实现也就是Fragment的切换。我们一起看看如何实现Fragment切换以及在切换时实现动画!

1、效果

在这里插入图片描述

2、切换Fragment

2.1、获取FragmentManager

  • 在Activity中获取FragmentManager

    使用getSupportFragmentManager方法获取

  • 在Fragment中获取FragmentManager

    Android3.0之前,使用getActivity().getSupportFragmentManager()方法间接获取

    Android3.0之后,使用getFragmentManager()方法直接获取

2.2、使用add方法切换Fragment

add方法:在当前的fragment上层添加一个fragment,当前的fragment不会消失,需要配合show方法和hide方法使用

private FirstFragment firstFragment;
private SecondFragment secondFragment;

//初始化,将FirstFragment显示到布局中
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_switch_use_add_demo);

  firstFragment = FirstFragment.newInstance("","");
  getSupportFragmentManager().beginTransaction().add(R.id.frame_content, firstFragment).commit();
}


@Override
public void onClick(View v) {
  if (v.getId() == R.id.switch_btn){
    step++;
    //add方法:在当前的fragment上层添加一个Fragment,当前的fragment不会消失,需要配合show方法和hide方法使用
    secondFragment = SecondFragment.newInstance("","");
    //添加SecondFragment
    getSupportFragmentManager().
      beginTransaction().
      add(R.id.frame_content, secondFragment).
      commit();
    //将FirstFragment隐藏
    getSupportFragmentManager().
      beginTransaction().
      hide(firstFragment).
      commit();
  }
}

2.3、使用replace方法切换Fragment

replace方法:相当于remove当前的fragment,然后add一个新的Fragment,当前的fragment会消失
private FirstFragment firstFragment;
private SecondFragment secondFragment;

//初始化,将FirstFragment显示到布局中
@Override
protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_switch_use_add_demo);

  firstFragment = FirstFragment.newInstance("","");
  getSupportFragmentManager().beginTransaction().add(R.id.frame_content, firstFragment).commit();
}


@Override
public void onClick(View v) {
  if (v.getId() == R.id.switch_btn){
    step++;
    //add方法:在当前的fragment上层添加一个Fragment,当前的fragment不会消失,需要配合show方法和hide方法使用
    secondFragment = SecondFragment.newInstance("","");
    //先Remove掉FirstFragment,然后添加SecondFragment
    getSupportFragmentManager().
      beginTransaction().
      replace(R.id.frame_content, secondFragment).
      commit();
  }
}

3、设置切换Fragment的动画

使用setCustomAnimations(int enter,int exit,int param3,int param4)方法设置Fragment的切换动画

3.1、setCustomAnimations的四个参数代表的意思:

  • enter:当Fragment被added或者attached到视图上时的动画
  • exit:当Fragment被removed或者detached到视图上时的动画
  • param3:当使用popBackStack()方法弹出栈顶的Fragment后,新的栈顶Fragment的出现动画。可以不设置
  • param4:当使用popBackStack()方法弹出栈顶的Fragment后,该Fragment的退出动画。可以不设置

3.2、定义enter的动画效果

x从左(-1屏初始位置)到右(屏幕初始位置),透明度从0.5到1

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">

    <translate
        android:fromXDelta="-100%p"
        android:toXDelta="0%p"/>

    <alpha
        android:fromAlpha="0.5"
        android:toAlpha="1"/>

</set>

3.3、定义exit的动画效果

x从左(屏幕初始位置)到右(+1屏初始位置),透明度从1到0.5

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:duration="1000">

    <translate
        android:fromXDelta="0%p"
        android:toXDelta="100%p" />

    <alpha
        android:fromAlpha="1"
        android:toAlpha="0.5"/>

</set>

3.4、设置动画

在replace切换fragment的基础上设置setCustomAnimations

getSupportFragmentManager().
      beginTransaction().
      setCustomAnimations(R.anim.fragment_enter,R.anim.fragment_exit).
      replace(R.id.frame_content, secondFragment).
      commit();

3.5、效果

在这里插入图片描述

3.6、注意

当前使用add切换Fragment时,例如当前Fragment是A,点击按钮,add一个新的Fragment,B。此时A并没有remove和detach,所以exit动画不会在A上执行;如果将add换成replace,那么A就会被remove,也就会执行exit动画了

3.7、相关博客

Android Fragment切换动画的2种实现方式

4. commit()和commitNowAllowingStateLoss()的区别

4.1. Fragment的状态机制

  1. 在onSaveInstanceState()调用commit()会报错,原因:
    	@Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);  // 系统保存Fragment的状态,这个状态会用于后续重建
        // 在这里执行 commit(),等于是一边保存旧状态,一边修改状态, 会抛异常
    }
    
  2. 在onSaveInstanceState()调用commitNowAllowingStateLoss()绕过状态限制,不会报错
  3. 当用户旋转屏幕时,会执行onSaveInstanceState方法保存Fragment状态,之后执行onCreate的super.onCreate(savedInstanceState)会把Fragment状态进行恢复,Fragment上的输入文本(如有)会被恢复
  4. 在onCreate时,不能直接创建Fragment实例,应该要先做判断,确保当有Fragment时不再重复创建,代码如下:
    	private static final String TAG_FIRST = "first_fragment";
    
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        // 先查找是否已存在
        firstFragment = (FirstFragment) getSupportFragmentManager()
            .findFragmentByTag(TAG_FIRST);
        
        if (firstFragment == null) {
            // 不存在才创建新的
            firstFragment = FirstFragment.newInstance("", "");
            getSupportFragmentManager()
                .beginTransaction()
                .add(R.id.container, firstFragment, TAG_FIRST)  // 设置 tag
                .commit();
        }
    }
    

4.2. 异步和同步

  1. commit()是异步操作
  2. commitNowAllowingStateLoss()是同步操作
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值