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

使用ViewPager2时Media3 ExoPlayer的PlayerView互相重叠问题

问题描述

我有一个横向ViewPager2,内部包含图片和视频两种独立布局的视图。设置resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM后,当两个视频相邻时,其中一个视频视图会与另一个重叠。使用其他缩放模式时运行正常,但我必须使用RESIZE_MODE_ZOOM模式。

左侧播放器出现重叠效果

相关代码

ViewPager2布局代码

<androidx.viewpager2.widget.ViewPager2
    android:id="@+id/pager"
    android:layout_width="match_parent"
    android:layout_height="358dp"
    android:orientation="horizontal" />

适配器代码(片段)

//.. 部分代码//
inner class HomePageVimeoViewHolder(private val binding: AppHomepageBoxVimeoItemBinding) :
    RecyclerView.ViewHolder(binding.root) {
//.. 部分代码//

    private lateinit var exoPlayer: ExoPlayer
    @OptIn(UnstableApi::class) private fun initializePlayer(videoUrl: String) {
        exoPlayer = ExoPlayer.Builder(mContext).build().apply {
            val mediaItem = MediaItem.fromUri(Uri.parse(videoUrl))
            setMediaItem(mediaItem)
            prepare()
            playWhenReady = true  // 播放器就绪时自动播放
            repeatMode = Player.REPEAT_MODE_ALL
            volume = 0f
        }
        binding.videoView.apply {
            player = exoPlayer
            useController = false  // 禁用ExoPlayer控制栏
            resizeMode = AspectRatioFrameLayout.RESIZE_MODE_ZOOM // 根据需求调整
        }
    }
//.. 部分代码//
}

Fragment代码(片段)

//.. 部分代码//
private fun setupViewPager() {
    homePageAdapter = HomePageAdapter(requireContext(), homePageBoxes)
    homePageAdapter.setOnItemClickListener(this)

    binding.pager.offscreenPageLimit = 2
    binding.pager.adapter = homePageAdapter
    binding.indicator.attachTo(binding.pager)

    // 使用ViewPager2实例初始化HorizontalSwipeViewPager2
    HorizontalSwipeViewPager2(binding.pager, requireContext())
}
//.. 部分代码//

Gradle配置(片段)

//.. 部分代码//
implementation 'androidx.media3:media3-exoplayer:1.2.0'
implementation 'androidx.media3:media3-ui:1.2.0'
//.. 部分代码//

解决方案

这个问题的核心是RESIZE_MODE_ZOOM会让视频视图超出父容器边界,再加上ViewPager2的预加载机制(offscreenPageLimit=2)让相邻视频视图同时存在,超出的部分就会和当前页面视图重叠。可以通过以下几种方式解决:

1. 给视频父容器添加裁剪属性

在视频项的布局文件(对应AppHomepageBoxVimeoItemBinding的布局)中,给videoView的父布局添加裁剪属性,确保超出父容器的部分被截断:

<!-- 视频项的根布局 -->
<LinearLayout
    ...
    android:clipChildren="true"
    android:clipToPadding="true">

    <com.google.android.exoplayer2.ui.StyledPlayerView
        android:id="@+id/videoView"
        ... />

</LinearLayout>

2. 设置ViewPager2页面间距

给ViewPager2添加页面间距,让相邻页面之间保留空隙,避免重叠:

// 在setupViewPager方法中添加
binding.pager.setPageMargin(16) // 单位为px,可根据需求调整数值

3. 优化播放器生命周期管理

只给当前可见的页面初始化播放器,不可见页面及时释放资源,减少视图重叠的概率:

// 在适配器中重写以下方法
override fun onViewAttachedToWindow(holder: RecyclerView.ViewHolder) {
    super.onViewAttachedToWindow(holder)
    if (holder is HomePageVimeoViewHolder) {
        // 重新初始化当前可见页面的播放器
        holder.initializePlayer(对应视频URL)
    }
}

override fun onViewDetachedFromWindow(holder: RecyclerView.ViewHolder) {
    super.onViewDetachedFromWindow(holder)
    if (holder is HomePageVimeoViewHolder) {
        // 释放不可见页面的播放器资源
        holder.exoPlayer.release()
    }
}

4. 约束视频视图的边界

确保StyledPlayerView的尺寸严格限制在父容器内,比如设置宽高为match_parent,同时父容器明确固定尺寸:

<com.google.android.exoplayer2.ui.StyledPlayerView
    android:id="@+id/videoView"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    ... />

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.03 01:21:21