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
相关产品推荐
相关产品推荐

