You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为ViewPager中各Fragment设置不同的进出动画?

给ViewPager中每个Fragment配置独立进出动画的解决方案

我之前也碰到过一模一样的需求——全局的PageTransformer确实能搞定统一动画,但要给每个Fragment单独配滑动进出效果就不够用了。这里给你几个经过验证的可行方案,你可以根据自己的场景选:

方案一:基于Fragment标识的自定义PageTransformer

这是最直接的思路:在自定义的PageTransformer里,根据当前页面对应的Fragment类型/标识,应用不同的动画逻辑。

步骤:

  1. 给每个Fragment加个区分标识,比如在Fragment的根View上设置Tag:
// 示例:在FirstFragment的onCreateView中
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_first, container, false);
    rootView.setTag("slide_left"); // 标记该Fragment使用左滑动画
    return rootView;
}
  1. 编写自定义PageTransformer,在transformPage方法里判断标识并执行对应动画:
public class PerFragmentPageTransformer implements ViewPager.PageTransformer {
    private ViewPager mViewPager;

    public PerFragmentPageTransformer(ViewPager viewPager) {
        mViewPager = viewPager;
    }

    @Override
    public void transformPage(@NonNull View page, float position) {
        String animTag = (String) page.getTag();
        if (animTag == null) return;

        switch (animTag) {
            case "slide_left":
                // 左滑进出动画逻辑
                if (position < -1) {
                    page.setAlpha(0);
                } else if (position <= 1) {
                    page.setAlpha(1 - Math.abs(position));
                    page.setTranslationX(page.getWidth() * -position);
                } else {
                    page.setAlpha(0);
                }
                break;
            case "fade_scale":
                // 淡入+缩放动画逻辑
                float scale = Math.max(0.85f, 1 - Math.abs(position));
                page.setScaleX(scale);
                page.setScaleY(scale);
                page.setAlpha(1 - Math.abs(position));
                break;
            case "slide_up":
                // 上滑进出动画逻辑
                page.setTranslationY(page.getHeight() * position);
                page.setAlpha(1 - Math.abs(position));
                break;
            // 其他Fragment的动画类型依次添加
        }
    }
}
  1. 给ViewPager设置这个Transformer:
mViewPager.setPageTransformer(false, new PerFragmentPageTransformer(mViewPager));

方案二:结合Fragment自带的进入/退出过渡动画

如果你的需求是页面切换完成时的过渡效果(而非滑动过程中的实时动画),可以直接用Fragment自身的过渡动画,和ViewPager配合使用:

步骤:

在每个Fragment的onCreate方法里设置独立的进入/退出动画:

// 示例:第一个Fragment——从右侧滑入,淡出退出
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setEnterTransition(new Slide(Gravity.RIGHT));
    setExitTransition(new Fade());
}
// 示例:第二个Fragment——缩放淡入,下滑退出
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setEnterTransition(new Scale());
    setExitTransition(new Slide(Gravity.BOTTOM));
}

注意:这个方案适合页面切换完成后的过渡效果,和ViewPager的滑动动画可能存在冲突,建议禁用ViewPager的默认动画,或者使用ViewPager2配合FragmentStateAdapter,兼容性更好。

方案三:自定义ViewPager监听滑动过程,精细控制动画

如果需要更极致的自定义(比如滑动过程中每个Fragment的动画实时变化),可以自定义ViewPager,监听页面滑动事件,手动给每个可见Fragment的View应用动画:

public class CustomViewPager extends ViewPager {
    public CustomViewPager(@NonNull Context context) {
        super(context);
        initPageChangeListener();
    }

    public CustomViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
        super(context, attrs);
        initPageChangeListener();
    }

    private void initPageChangeListener() {
        addOnPageChangeListener(new OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                FragmentPagerAdapter adapter = (FragmentPagerAdapter) getAdapter();
                if (adapter == null) return;

                // 左侧Fragment的退出动画
                Fragment leftFragment = adapter.getItem(position);
                if (leftFragment != null && leftFragment.getView() != null) {
                    View leftView = leftFragment.getView();
                    leftView.setTranslationX(positionOffsetPixels);
                    leftView.setAlpha(1 - positionOffset);
                }

                // 右侧Fragment的进入动画(如果存在)
                if (position + 1 < adapter.getCount()) {
                    Fragment rightFragment = adapter.getItem(position + 1);
                    if (rightFragment != null && rightFragment.getView() != null) {
                        View rightView = rightFragment.getView();
                        rightView.setTranslationX(getWidth() - positionOffsetPixels);
                        rightView.setAlpha(positionOffset);
                    }
                }
            }

            @Override
            public void onPageSelected(int position) {}

            @Override
            public void onPageScrollStateChanged(int state) {}
        });
    }
}

注意事项:

  • 确保Fragment的View已经初始化完成,否则getView()会返回null,建议在Fragment的onViewCreated里做初始化标记,或者在动画逻辑里加非空判断。
  • 优先使用硬件加速的属性(如translationX、alpha、scaleX),避免使用layout()之类的耗时操作,防止卡顿。
  • 如果使用ViewPager2,获取Fragment的方法是((FragmentStateAdapter) getAdapter()).getFragment(position),需要注意AndroidX版本的兼容性。

内容的提问来源于stack exchange,提问作者PBS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:54:54