Fragment的setEnterTransition()与setExitTransition()方法原理及ViewPager动画失效问题
嘿,我来帮你搞清楚这个问题!
Fragment的
setEnterTransition()和setExitTransition()到底怎么工作? 先给你拆解这两个方法的核心逻辑:
setEnterTransition():这个方法定义的是Fragment在被添加到Activity、从隐藏状态转为显示,或者从后台栈回到前台时,进入屏幕的过渡动画。注意,它只会在FragmentTransaction执行add()、show()、replace()(作为被添加的新Fragment)这类操作时触发。setExitTransition():对应的是Fragment在被从Activity移除、转为隐藏状态,或者被替换并压入后台栈时,离开屏幕的过渡动画,触发场景是FragmentTransaction执行remove()、hide()、replace()(作为被替换的旧Fragment)这类操作。
为什么你的ViewPager里动画没生效?
问题出在ViewPager的切换逻辑上!ViewPager默认是通过setUserVisibleHint()(旧版)或onHiddenChanged()(新版)来控制Fragment的显示与隐藏,它并没有调用那些能触发过渡动画的FragmentTransaction方法(比如show()/hide()或者replace())。所以你在onCreateView()里设置的动画根本没被触发。
给ViewPager加Fragment切换动画的正确方案
这里有两种常用的解决思路,按需选择:
1. 直接给ViewPager设置页面切换动画
这是最直接的方式,不需要在Fragment里配置过渡动画,直接给ViewPager本身加PageTransformer:
ViewPager viewPager = findViewById(R.id.your_viewpager_id); // 自定义滑动动画,这里模拟你想要的从右侧滑入滑出效果 viewPager.setPageTransformer(true, new ViewPager.PageTransformer() { @Override public void transformPage(@NonNull View page, float position) { // position的取值范围:-1(页面完全在左侧)到1(页面完全在右侧) if (position < -1) { page.setAlpha(0); } else if (position <= 0) { // 当前页面从左侧滑入 page.setAlpha(1); page.setTranslationX(page.getWidth() * -position); } else if (position <= 1) { // 下一个页面从右侧滑入 page.setAlpha(1 - position); page.setTranslationX(page.getWidth() * -position); } else { page.setAlpha(0); } } });
2. 改用ViewPager2 + 自定义过渡(推荐)
如果你已经升级到ViewPager2,它的动画支持更灵活,还能结合Fragment的过渡动画使用。你可以通过自定义PageTransformer来实现:
ViewPager2 viewPager2 = findViewById(R.id.your_viewpager2_id); viewPager2.setAdapter(new FragmentStateAdapter(this) { @NonNull @Override public Fragment createFragment(int position) { // 返回对应位置的Fragment实例 return position == 0 ? new FirstFragment() : new SecondFragment(); } @Override public int getItemCount() { return 2; } }); // 设置自定义切换动画,比如Slide效果 viewPager2.setPageTransformer(new SlidePageTransformer()); // 自定义Transformer示例 private static class SlidePageTransformer implements ViewPager2.PageTransformer { @Override public void transformPage(@NonNull View page, float position) { page.setTranslationX(-position * page.getWidth()); page.setAlpha(1 - Math.abs(position)); } }
额外:如果一定要用Fragment的过渡动画
那你得放弃ViewPager的默认切换逻辑,改用手动的FragmentTransaction来切换Fragment(比如配合底部导航栏),同时要注意两个关键点:
- 在Activity的主题里启用内容过渡:
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <item name="android:windowContentTransitions">true</item> </style>
- 执行FragmentTransaction时必须开启重排序:
// 比如点击按钮切换Fragment getSupportFragmentManager() .beginTransaction() .setReorderingAllowed(true) // 这行必须加,过渡动画才会生效 .replace(R.id.fragment_container, new TargetFragment()) .addToBackStack(null) .commit();
内容的提问来源于stack exchange,提问作者ANAL SHAH
相关产品推荐
相关产品推荐

