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

全局锁定竖屏的App中,如何单独旋转ExoPlayer播放框架?

嘿,我之前刚好处理过一模一样的需求,给你分享两个靠谱的实现方案,亲测有效:

方案一:直接旋转ExoPlayer控件(最快捷)

这个思路很直接——既然整个App固定竖屏,那我们就只旋转ExoPlayer的播放视图,同时调整布局让它占满屏幕,隐藏其他无关UI。

步骤拆解:

  1. 监听全屏按钮点击,切换播放视图的旋转状态
  2. 调整布局参数,横屏时让播放器占满整个屏幕,竖屏时恢复原尺寸
  3. 修正触摸坐标(可选但重要),因为旋转后触摸点会和实际控件位置错位

代码示例(Kotlin):

// 假设playerView是你的ExoPlayer容器,otherViewGroup是页面其他UI区域
private var isFullScreen = false

fun togglePlayerFullScreen() {
    isFullScreen = !isFullScreen
    if (isFullScreen) {
        // 旋转播放器到横屏角度(90度),加个动画更流畅
        playerView.animate().rotation(90f).setDuration(300).start()
        // 隐藏其他UI,让播放器占满屏幕
        otherViewGroup.visibility = View.GONE
        playerView.layoutParams = FrameLayout.LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT
        )
        // 隐藏系统状态栏和导航栏,提升沉浸感
        hideSystemUI()
    } else {
        // 切回竖屏状态
        playerView.animate().rotation(0f).setDuration(300).start()
        // 恢复原布局和UI显示
        otherViewGroup.visibility = View.VISIBLE
        playerView.layoutParams = LinearLayout.LayoutParams(
            LinearLayout.LayoutParams.MATCH_PARENT,
            resources.getDimensionPixelSize(R.dimen.default_player_height)
        )
        // 显示系统UI
        showSystemUI()
    }
}

// 处理系统UI显示/隐藏
private fun hideSystemUI() {
    window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
            or View.SYSTEM_UI_FLAG_FULLSCREEN
            or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION)
}

private fun showSystemUI() {
    window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
}

修复触摸错位问题:

旋转后,触摸事件的坐标会和控件实际位置不匹配,需要重写触摸监听转换坐标:

playerView.setOnTouchListener { v, event ->
    if (isFullScreen) {
        // 旋转90度后,x和y坐标需要互换并调整
        val rotatedX = event.y
        val rotatedY = v.width - event.x
        val correctedEvent = MotionEvent.obtain(
            event.downTime,
            event.eventTime,
            event.action,
            rotatedX,
            rotatedY,
            event.metaState
        )
        val result = v.onTouchEvent(correctedEvent)
        correctedEvent.recycle()
        return@setOnTouchListener result
    }
    v.onTouchEvent(event)
}
方案二:用TextureView手动控制视频渲染(更灵活)

如果需要更精细地控制视频的缩放和旋转,可以用TextureView作为ExoPlayer的渲染载体,通过ExoPlayer的视频尺寸回调来调整渲染参数。

步骤拆解:

  1. 给PlayerView设置自定义的TextureView
  2. 监听ExoPlayer的视频尺寸变化,动态调整TextureView的旋转、缩放比例
  3. 同样配合布局调整和系统UI控制实现全屏效果

代码示例:

// 初始化时设置TextureView
val textureView = TextureView(context)
playerView.setVideoTextureView(textureView)

// 监听视频尺寸变化,调整渲染参数
player.addListener(object : Player.Listener {
    override fun onVideoSizeChanged(videoSize: VideoSize) {
        super.onVideoSizeChanged(videoSize)
        if (isFullScreen) {
            // 横屏时旋转TextureView
            textureView.rotation = 90f
            // 计算缩放比例,让视频铺满屏幕
            val screenHeight = resources.displayMetrics.heightPixels.toFloat()
            val screenWidth = resources.displayMetrics.widthPixels.toFloat()
            val scaleX = screenHeight / videoSize.height
            val scaleY = screenWidth / videoSize.width
            val scale = max(scaleX, scaleY)
            textureView.scaleX = scale
            textureView.scaleY = scale
        } else {
            // 竖屏时恢复默认状态
            textureView.rotation = 0f
            val scaleX = resources.displayMetrics.widthPixels.toFloat() / videoSize.width
            val scaleY = playerView.height.toFloat() / videoSize.height
            val scale = min(scaleX, scaleY)
            textureView.scaleX = scale
            textureView.scaleY = scale
        }
    }
})

// 全屏切换逻辑和方案一一致,这里省略重复代码
注意事项
  • 确保你的App已经在Manifest里固定了竖屏:android:screenOrientation="portrait"
  • 如果使用SurfaceView,旋转后可能会有画面闪烁问题,TextureView的兼容性更好,但性能略逊于SurfaceView,可以根据需求选择
  • 横屏时记得处理返回键逻辑,点击返回键要切回竖屏状态

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.19 09:04:07