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

ViewPager滑动时视频音频异常播放,求仿Instagram播放逻辑实现方案

ViewPager视频生命周期控制优化(仿Instagram滑动逻辑)

问题根源

原代码在onPageSelected回调中触发视频播放/暂停,但这个回调会在页面刚进入选中状态(滑动到一半时)就执行,导致前后两个视频同时播放。Instagram的逻辑是滑动完全停止、目标页面完全显示后,才播放当前页视频,同时暂停上一页视频。

实现方案

核心思路

  • 监听ViewPager的滑动状态,仅在滑动停止(SCROLL_STATE_IDLE)时处理视频生命周期
  • 避免直接调用adapter.getItem()(该方法会创建新Fragment实例,而非获取当前已加载的Fragment),通过FragmentManager获取已加载的Fragment实例
  • 记录上一个活跃页面的位置,避免重复执行播放/暂停操作

代码实现

1. 替换原OnPageChangeListener

private int lastPlayedPosition = 0;
private final ViewPager.OnPageChangeListener pageChangeListener = new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        // 不再在这里处理播放逻辑,交给滑动停止时处理
    }

    @Override
    public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
        // 无需处理滚动中事件
    }

    @Override
    public void onPageScrollStateChanged(int state) {
        // 仅当滑动停止时执行逻辑
        if (state == ViewPager.SCROLL_STATE_IDLE) {
            int currentPosition = viewPager.getCurrentItem();
            // 暂停上一个页面的视频
            FragmentLifecycle lastFragment = getFragmentByPosition(lastPlayedPosition);
            if (lastFragment != null) {
                lastFragment.onPauseFragment();
            }
            // 播放当前页面的视频
            FragmentLifecycle currentFragment = getFragmentByPosition(currentPosition);
            if (currentFragment != null) {
                currentFragment.onResumeFragment();
            }
            lastPlayedPosition = currentPosition;
        }
    }
};

2. 实现获取已加载Fragment的工具方法

private FragmentLifecycle getFragmentByPosition(int position) {
    // FragmentPagerAdapter的Fragment标签规则:"android:switcher:" + ViewPagerID + ":" + position
    String tag = "android:switcher:" + viewPager.getId() + ":" + position;
    Fragment fragment = getSupportFragmentManager().findFragmentByTag(tag);
    if (fragment instanceof FragmentLifecycle) {
        return (FragmentLifecycle) fragment;
    }
    return null;
}

3. 优化Activity生命周期处理

@Override
protected void onPause() {
    super.onPause();
    // 暂停当前播放的视频
    FragmentLifecycle currentFragment = getFragmentByPosition(lastPlayedPosition);
    if (currentFragment != null) {
        currentFragment.onPauseFragment();
    }
}

@Override
protected void onResume() {
    super.onResume();
    // 恢复当前页面的视频播放
    FragmentLifecycle currentFragment = getFragmentByPosition(viewPager.getCurrentItem());
    if (currentFragment != null) {
        currentFragment.onResumeFragment();
    }
}

@Override
protected void onDestroy() {
    super.onDestroy();
    // 移除ViewPager监听,避免内存泄漏
    viewPager.removeOnPageChangeListener(pageChangeListener);
}

关键说明

  • 必须通过FragmentManager的findFragmentByTag获取已加载的Fragment,不能直接调用adapter.getItem(),否则会创建新的Fragment实例,无法控制已显示的视频
  • 滑动状态判断是核心:只有当SCROLL_STATE_IDLE时才处理,确保页面完全切换后再执行播放/暂停
  • 记录lastPlayedPosition可以避免重复操作,比如连续滑动时不会重复暂停同一个页面

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 09:23:09