Fragment也可以添加切换动画,由于Fragment是在API 11中新引入的类,因此为了兼容性我们需要使用support-v4这个兼容包,在这种情况下我们可以通过FragmentTransition中的setCustomAnimations()方法来添加切换动画。
这个切换动画需要是View动画,之所以不能采用属性动画是因为属性动画也是API 11新引入的。
在res/anim目录创建动画:
- fragment_enter_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true">
<alpha
android:fromAlpha="0"
android:toAlpha="1"/>
<translate
android:fromXDelta="100%"
android:toXDelta="0"/>
</set>
- fragment_exit_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0"/>
<translate
android:fromXDelta="0"
android:toXDelta="100%"/>
</set>
- fragment_pop_enter_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true">
<alpha
android:fromAlpha="0.0"
android:toAlpha="1.0"/>
<rotate
android:fromDegrees="0"
android:toDegrees="360"
android:pivotX="50%"
android:pivotY="50%"/>
</set>
- fragment_pop_exit_anim.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
android:duration="1000"
android:fillAfter="true">
<alpha
android:fromAlpha="1.0"
android:toAlpha="0.0" />
<rotate
android:fromDegrees="360"
android:pivotX="50%"
android:pivotY="50%"
android:toDegrees="0" />
</set>
- Fragment代码
public class SwitchFragment extends Fragment {
private AddBackStackListener listener;
private Button button;
@Override
public void onAttach(Context context) {
super.onAttach(context);
if (context instanceof AddBackStackListener) {
listener = (AddBackStackListener) context;
} else {
throw new RuntimeException("activity must be implements AddBackStackListener!");
}
}
@Override
public void onDetach() {
super.onDetach();
listener = null;
}
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.fragment_switch, container, false);
button = view.findViewById(R.id.btn_add_fragment);
return view;
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (listener != null) {
listener.addBackStack(new SwitchFragment());
}
}
});
}
}
- Activity代码
public class FragmentSwitchActivity extends AppCompatActivity implements AddBackStackListener {
private Button button;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_fragment_switch);
button = findViewById(R.id.btn_switch_fragment);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
addToBackStack(new SwitchFragment());
button.setVisibility(View.GONE);
}
});
}
/**
* fragment回调接口,添加Fragment到栈中
*/
@Override
public void addBackStack(Fragment fragment) {
addToBackStack(fragment);
}
private void addToBackStack(Fragment fragment) {
FragmentManager fragmentManager = getSupportFragmentManager();
FragmentTransaction transaction = fragmentManager.beginTransaction();
// 系统提供的Fragment切换动画
// FragmentTransaction.TRANSIT_FRAGMENT_FADE: 淡入效果
// FragmentTransaction.TRANSIT_FRAGMENT_OPEN:
// FragmentTransaction.TRANSIT_FRAGMENT_CLOSE:
// FragmentTransaction.TRANSIT_ENTER_MASK:
// FragmentTransaction.TRANSIT_EXIT_MASK:
// FragmentTransaction.TRANSIT_NONE:
// FragmentTransaction.TRANSIT_UNSET:
// transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
// transaction.setCustomAnimations(R.anim.fragment_enter_anim, R.anim.fragment_exit_anim);
// 加入Fragment压栈和弹栈动画
// 存在的问题:Fragment压栈的动画R.anim.pop_enter_anim没有执行,压栈都是执行fragment_enter_anim
transaction.setCustomAnimations(R.anim.fragment_enter_anim, R.anim.fragment_exit_anim,
R.anim.fragment_pop_enter_anim, R.anim.fragment_pop_eixt_anim);
transaction.replace(R.id.fragment_container, fragment).addToBackStack(null);
transaction.commit();
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
onBackPressed();
}
return true;
}
@Override
public void onBackPressed() {
fragmentPopStack();
}
private void fragmentPopStack() {
FragmentManager fragmentManager = getSupportFragmentManager();
Log.i("FragmentSwitchActivity", fragmentManager.getBackStackEntryCount() + "");
if (fragmentManager.getBackStackEntryCount() > 0) {
// 这里的Fragment弹栈会有指定的R.anim.fragment_pop_exit_anim.xml动画效果
fragmentManager.popBackStack();
if (fragmentManager.getBackStackEntryCount() == 1) {
button.setVisibility(View.VISIBLE);
}
} else {
finish();
}
}
}