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

ViewPager结合View与Fragment实现视频播放列表的播放异常问题

解决ViewPager切换时视频播放页面错位的问题

嘿,我来帮你搞定这个头疼的问题!你遇到的核心问题是ViewPager的预加载机制+播放器实例没有和对应页面绑定,导致切换页面时播放器还“粘”在最后打开的页面上。下面给你一步步的解决方案:

1. 让每个Fragment独立管理自己的播放器

别在PagerAdapter里全局存播放器实例了,让每个Fragment自己初始化、持有、释放对应的视频播放器。这样每个页面的播放状态都是独立的,不会串页。

比如写一个VideoFragment:

public class VideoFragment extends Fragment {
    private VideoView videoView;
    private String videoUrl;

    // 静态方法传参创建Fragment
    public static VideoFragment newInstance(String videoUrl) {
        VideoFragment fragment = new VideoFragment();
        Bundle args = new Bundle();
        args.putString("VIDEO_URL", videoUrl);
        fragment.setArguments(args);
        return fragment;
    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View rootView = inflater.inflate(R.layout.fragment_video_player, container, false);
        videoView = rootView.findViewById(R.id.video_view);
        videoUrl = getArguments().getString("VIDEO_URL");
        setupPlayer();
        return rootView;
    }

    private void setupPlayer() {
        videoView.setVideoPath(videoUrl);
        // 准备好后自动播放
        videoView.setOnPreparedListener(mediaPlayer -> mediaPlayer.start());
    }

    // 页面暂停时暂停播放
    @Override
    public void onPause() {
        super.onPause();
        if (videoView != null && videoView.isPlaying()) {
            videoView.pause();
        }
    }

    // 页面恢复时继续播放
    @Override
    public void onResume() {
        super.onResume();
        if (videoView != null) {
            videoView.start();
        }
    }

    // 销毁页面时释放播放器资源
    @Override
    public void onDestroyView() {
        super.onDestroyView();
        if (videoView != null) {
            videoView.stopPlayback();
            videoView = null;
        }
    }
}

2. 用FragmentPagerAdapter管理页面(别混写View和Fragment)

你之前用View+Fragment混合布局容易出问题,建议统一用Fragment来做ViewPager的页面。用FragmentPagerAdapter时,记得加上BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT,这个参数会让只有当前显示的Fragment走到onResume状态,其他预加载的Fragment停在onStart,刚好配合我们上面写的播放逻辑。

PagerAdapter代码示例:

public class VideoPagerAdapter extends FragmentPagerAdapter {
    private List<String> videoUrlList;

    public VideoPagerAdapter(FragmentManager fm, List<String> videoUrls) {
        // 关键参数:只让当前Fragment触发onResume
        super(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT);
        this.videoUrlList = videoUrls;
    }

    @Override
    public Fragment getItem(int position) {
        return VideoFragment.newInstance(videoUrlList.get(position));
    }

    @Override
    public int getCount() {
        return videoUrlList.size();
    }
}

3. 在Activity里处理页面切换的播放状态

虽然上面的生命周期回调已经能处理大部分情况,但保险起见,你可以监听ViewPager的页面切换事件,手动控制上一页暂停、当前页播放:

public class PlaylistActivity extends AppCompatActivity {
    private ViewPager viewPager;
    private VideoPagerAdapter adapter;
    private VideoFragment currentFragment;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_playlist);

        // 获取传过来的播放列表和起始位置
        List<String> videoUrls = getIntent().getStringArrayListExtra("PLAYLIST");
        int startPos = getIntent().getIntExtra("START_POS", 0);

        viewPager = findViewById(R.id.view_pager);
        adapter = new VideoPagerAdapter(getSupportFragmentManager(), videoUrls);
        viewPager.setAdapter(adapter);
        viewPager.setCurrentItem(startPos);

        // 初始化当前显示的Fragment
        currentFragment = (VideoFragment) adapter.getItem(startPos);

        // 监听页面切换
        viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {}

            @Override
            public void onPageSelected(int position) {
                // 暂停上一页的视频
                if (currentFragment != null) {
                    currentFragment.onPause();
                }
                // 获取并播放当前页的视频
                currentFragment = (VideoFragment) adapter.getItem(position);
                currentFragment.onResume();
            }

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

4. 如果你非要保留View+Fragment混合布局

如果因为某些原因不能全用Fragment,那你需要给每个View设置唯一的Tag,在PagerAdapter的instantiateItem里初始化对应View的播放器,切换页面时通过Tag找到对应的View和播放器,暂停其他的,播放当前的。比如:

@Override
public Object instantiateItem(ViewGroup container, int position) {
    View view = inflater.inflate(R.layout.item_video_page, container, false);
    view.setTag("VIDEO_PAGE_" + position);
    VideoView videoView = view.findViewById(R.id.video_view);
    videoView.setVideoPath(videoUrlList.get(position));
    container.addView(view);
    return view;
}

然后在页面切换时:

viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
    @Override
    public void onPageSelected(int position) {
        // 遍历所有页面,暂停非当前页的播放
        for (int i = 0; i < viewPager.getChildCount(); i++) {
            View page = viewPager.findViewWithTag("VIDEO_PAGE_" + i);
            if (page != null) {
                VideoView vv = page.findViewById(R.id.video_view);
                if (i != position && vv.isPlaying()) {
                    vv.pause();
                } else if (i == position) {
                    vv.start();
                }
            }
        }
    }
});

这个方法不如全用Fragment优雅,但也能解决问题。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.21 04:03:38