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

Android中如何使用ViewPager2实现类似TikTok的上下滑动切换视频功能

使用Java + ViewPager2 实现TikTok风格上下滑动视频播放

以下方案适配Android Studio 2020.3.1.25版本,全程使用Java语言实现:

1. 导入必要依赖

首先打开模块级build.gradle文件,在dependencies块中添加如下依赖:

// ViewPager2 核心依赖
implementation "androidx.viewpager2:viewpager2:1.0.0"
// ExoPlayer 视频播放依赖,Google官方推荐的视频播放组件
implementation "com.google.android.exoplayer:exoplayer:2.18.7"

添加完成后点击同步Gradle即可。

2. 编写核心布局文件

2.1 主页面布局(activity_main.xml)

只需要一个全屏的ViewPager2,设置滑动方向为垂直:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <androidx.viewpager2.widget.ViewPager2
        android:id="@+id/viewPager2"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"/>

</androidx.constraintlayout.widget.ConstraintLayout>

2.2 单个视频item布局(item_video.xml)

每个页面只需要一个占满全屏的ExoPlayer的PlayerView:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.exoplayer2.ui.PlayerView
        android:id="@+id/playerView"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:keepScreenOn="true"
        app:use_controller="false"/>

</FrameLayout>

3. 定义视频数据实体类

创建VideoBean.java用来存储每个视频的相关信息:

public class VideoBean {
    private String videoUrl;
    private String coverUrl;

    public VideoBean(String videoUrl, String coverUrl) {
        this.videoUrl = videoUrl;
        this.coverUrl = coverUrl;
    }
    // 省略getter、setter方法
}

4. 实现ViewPager2适配器

ViewPager2的适配器直接继承RecyclerView.Adapter即可:

public class VideoAdapter extends RecyclerView.Adapter<VideoAdapter.VideoViewHolder> {
    private List<VideoBean> videoList;
    private ExoPlayer currentPlayer;

    public VideoAdapter(List<VideoBean> videoList) {
        this.videoList = videoList;
    }

    @NonNull
    @Override
    public VideoViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
        View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_video, parent, false);
        return new VideoViewHolder(view);
    }

    @Override
    public void onBindViewHolder(@NonNull VideoViewHolder holder, int position) {
        // 这里只绑定数据,播放逻辑放到页面选中时处理,避免同时加载多个视频
        holder.videoUrl = videoList.get(position).getVideoUrl();
    }

    @Override
    public int getItemCount() {
        return videoList.size();
    }

    // 页面选中时调用此方法播放当前视频
    public void playVideo(int position, VideoViewHolder holder) {
        // 先释放之前的播放器资源
        if (currentPlayer != null) {
            currentPlayer.release();
        }
        // 初始化新的播放器
        Context context = holder.itemView.getContext();
        currentPlayer = new ExoPlayer.Builder(context).build();
        holder.playerView.setPlayer(currentPlayer);
        // 设置播放源
        MediaItem mediaItem = MediaItem.fromUri(holder.videoUrl);
        currentPlayer.setMediaItem(mediaItem);
        currentPlayer.setRepeatMode(Player.REPEAT_MODE_ONE);
        currentPlayer.prepare();
        currentPlayer.play();
    }

    // 释放所有播放器资源
    public void releasePlayer() {
        if (currentPlayer != null) {
            currentPlayer.release();
            currentPlayer = null;
        }
    }

    public static class VideoViewHolder extends RecyclerView.ViewHolder {
        PlayerView playerView;
        String videoUrl;
        public VideoViewHolder(@NonNull View itemView) {
            super(itemView);
            playerView = itemView.findViewById(R.id.playerView);
        }
    }
}

5. 主页面逻辑实现

在MainActivity.java中绑定适配器,添加页面切换监听:

public class MainActivity extends AppCompatActivity {
    private ViewPager2 viewPager2;
    private VideoAdapter adapter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        viewPager2 = findViewById(R.id.viewPager2);
        // 模拟测试数据,替换为你自己的视频地址
        List<VideoBean> videoList = new ArrayList<>();
        videoList.add(new VideoBean("你的视频地址1", ""));
        videoList.add(new VideoBean("你的视频地址2", ""));
        videoList.add(new VideoBean("你的视频地址3", ""));
        // 设置适配器
        adapter = new VideoAdapter(videoList);
        viewPager2.setAdapter(adapter);
        // 配置预加载页数,提升滑动体验
        viewPager2.setOffscreenPageLimit(1);
        // 添加页面切换监听
        viewPager2.registerOnPageChangeCallback(new ViewPager2.OnPageChangeCallback() {
            @Override
            public void onPageSelected(int position) {
                super.onPageSelected(position);
                // 获取当前选中的ViewHolder,播放视频
                RecyclerView recyclerView = (RecyclerView) viewPager2.getChildAt(0);
                VideoAdapter.VideoViewHolder viewHolder = (VideoAdapter.VideoViewHolder) recyclerView.findViewHolderForAdapterPosition(position);
                if (viewHolder != null) {
                    adapter.playVideo(position, viewHolder);
                }
            }
        });
        // 首次进入自动播放第一个视频
        viewPager2.post(() -> adapter.playVideo(0, (VideoAdapter.VideoViewHolder) ((RecyclerView)viewPager2.getChildAt(0)).findViewHolderForAdapterPosition(0)));
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (adapter != null) {
            adapter.releasePlayer();
        }
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (adapter != null) {
            adapter.releasePlayer();
        }
    }
}

可选优化点

  • 给PlayerView添加封面图,避免视频加载完成前出现黑屏
  • 添加缓冲加载提示,提升弱网环境下的用户体验
  • 处理视频播放异常的重试逻辑
  • 添加单击暂停/播放、双击点赞等交互逻辑
  • 如果需要禁用左右滑动能力,可调用viewPager2的setUserInputEnabled(false)方法

内容的提问来源于stack exchange,提问作者Stan S.

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.26 02:36:04