Pixel 7上Jetpack Compose+ExoPlayer竖屏初始加载视频裁剪问题
解决Jetpack Compose中ExoPlayer竖屏首次加载视频裁剪问题
问题核心
首次竖屏打开时,ExoPlayer的Surface还未适配Compose fillMaxSize布局的最终尺寸,导致视频渲染时出现裁剪;而横竖屏切换会触发布局重测与Surface重新适配,因此问题消失。直接去掉fillMaxSize虽能解决,但无法满足控制器置于底部的布局需求。
可行解决方案
1. 监听布局尺寸变化,动态适配Surface
利用Compose的Modifier.onSizeChanged监听视频容器的尺寸,待尺寸稳定(宽高均大于0)后,再配置ExoPlayer的Surface或调整视频缩放模式:
Box(modifier = Modifier.fillMaxSize() .onSizeChanged { size -> if (size.width > 0 && size.height > 0) { exoPlayer?.videoScalingMode = C.VIDEO_SCALING_MODE_FIT exoPlayerView?.layoutParams = FrameLayout.LayoutParams( size.width, size.height ) } }) { AndroidView( factory = { context -> StyledPlayerView(context).apply { player = exoPlayer useController = false // 自定义控制器 } }, modifier = Modifier.matchParentSize() ) // 底部自定义控制器 Row( modifier = Modifier.align(Alignment.BottomCenter) .fillMaxWidth() .background(Color.Black.copy(alpha = 0.5f)) .padding(8.dp) ) { // 播放/暂停、进度条等控件 } }
2. 结合AspectRatio修饰符固定视频比例
在fillMaxSize的容器内,给视频区域添加aspectRatio修饰符,确保视频渲染时匹配原始比例,避免裁剪:
Box(modifier = Modifier.fillMaxSize()) { AndroidView( factory = { context -> StyledPlayerView(context).apply { player = exoPlayer useController = false resizeMode = AspectRatioFrameLayout.RESIZE_MODE_FIT } }, modifier = Modifier.fillMaxSize() .aspectRatio(16f / 9f) // 替换为视频实际宽高比 .align(Alignment.Center) ) // 底部控制器 // ... }
这里的关键是给StyledPlayerView设置resizeMode = RESIZE_MODE_FIT,配合Compose的aspectRatio修饰符,让视频在容器内按比例适配,同时外层fillMaxSize保证控制器能置于底部。
3. 延迟初始化ExoPlayer至布局完成
通过ViewTreeObserver监听布局完成事件,等Compose布局稳定后再初始化ExoPlayer,避免Surface提前渲染:
AndroidView( factory = { context -> val playerView = StyledPlayerView(context) playerView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener { override fun onGlobalLayout() { playerView.viewTreeObserver.removeOnGlobalLayoutListener(this) val exoPlayer = ExoPlayer.Builder(context).build() exoPlayer.setMediaItem(MediaItem.fromUri(uri)) exoPlayer.playWhenReady = true playerView.player = exoPlayer } }) playerView }, modifier = Modifier.fillMaxSize() )
为什么之前的方案无效?
AspectRatioFrameLayout:若未同步Compose的布局更新时机,Surface可能在布局测量完成前就已初始化,导致比例适配失效。- 初始化时强制切换横竖屏:属于临时hack,部分设备上布局未完全稳定就切回竖屏,Surface仍未适配正确尺寸,问题复现。
内容的提问来源于stack exchange,提问作者Anusha C
相关产品推荐
相关产品推荐

