能否以编程方式定义Fragment切换时的过渡动画?
当然有啦!其实Android早就提供了完全用代码定义动画来实现Fragment切换的方案,不用再局限于XML动画文件。我来给你拆解几种实用的实现方式:
setCustomAnimations的重载方法(API 26+) 从Android 8.0(API 26)开始,FragmentTransaction新增了接受Animator对象的重载方法,你可以直接把用代码写好的动画传进去,非常直观:
// 用代码定义Fragment的进入和退出动画 Animator enterAnimator = ObjectAnimator.ofFloat(null, "translationX", 1000f, 0f) .setDuration(300); Animator exitAnimator = ObjectAnimator.ofFloat(null, "translationX", 0f, -1000f) .setDuration(300); // 把动画绑定到Fragment切换操作 getSupportFragmentManager().beginTransaction() .setCustomAnimations(enterAnimator, exitAnimator) .replace(R.id.fragment_container, new TargetFragment()) .addToBackStack(null) .commit();
这里要注意:第一个参数传null就好,因为系统会自动把Fragment的根View作为动画的目标对象,不用手动指定。
FragmentAnimator(兼容低版本) 如果你的App需要支持API 26以下的设备,可以通过重写Fragment的onCreateAnimator方法来返回自定义的动画逻辑:
public class TargetFragment extends Fragment { @Override public Animator onCreateAnimator(int transit, boolean enter, int nextAnim) { // 根据进入/退出状态返回对应的动画 if (enter) { // 进入动画:从右侧滑入屏幕 return ObjectAnimator.ofFloat(getView(), "translationX", 1000f, 0f) .setDuration(300); } else { // 退出动画:滑出到屏幕左侧 return ObjectAnimator.ofFloat(getView(), "translationX", 0f, -1000f) .setDuration(300); } } }
这样只要你正常执行Fragment的replace/add操作,这个自定义动画就会自动被触发,不用在Transaction里额外设置动画参数。
如果想要更灵活的动画(比如共享元素过渡、组合动画等),可以用Android的Transition框架,它能实现比基础Animator更丰富的视觉效果:
// 定义滑入滑出的Transition Slide enterTransition = new Slide(Gravity.RIGHT); enterTransition.setDuration(300); Slide exitTransition = new Slide(Gravity.LEFT); exitTransition.setDuration(300); // 绑定到FragmentTransaction getSupportFragmentManager().beginTransaction() .setReorderingAllowed(true) // 开启过渡优化,让动画更流畅 .replace(R.id.fragment_container, new TargetFragment()) .addToBackStack(null) .commit();
然后在目标Fragment的onCreateView里启用过渡:
@Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View rootView = inflater.inflate(R.layout.fragment_target, container, false); // 应用过渡动画 TransitionManager.beginDelayedTransition(container, enterTransition); return rootView; }
这种方式还支持共享元素过渡,只要在Transaction里调用addSharedElement(view, "transition_tag"),再在两个Fragment的布局里给对应View设置相同的transitionName属性就行。
这些方案都能让你完全用代码掌控Fragment的切换动画,不用再依赖XML文件,你可以根据自己的API版本兼容需求和动画复杂度来选择合适的方式~
内容的提问来源于stack exchange,提问作者Vasiliy

