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

