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

求助:如何实现ExoPlayer在RecyclerView与ViewPager中的全屏播放

Hey there! I’ve been in your shoes before—adding fullscreen support to ExoPlayer when it’s nested in RecyclerView or ViewPager can feel tricky at first, but it’s totally doable with a few key steps. Let me walk you through how I’ve implemented it in similar projects:

Core Idea

Fullscreen playback essentially boils down to moving ExoPlayer's SurfaceView/TextureView from its original layout container to a full-screen container (like the Activity's DecorView), switching the screen orientation, and hiding system UI. When exiting fullscreen, you just reverse this process and restore the player's state.

1. Prepare Full-Screen Container & State Tracking

First, add a full-screen FrameLayout to your Activity's root layout (set it to GONE by default) to hold the player when in fullscreen:

<!-- Place this as the top-level view in your Activity layout -->
<FrameLayout
    android:id="@+id/fullscreen_container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:visibility="gone"/>

Then, track key player states to ensure seamless transition:

// Inside your custom player wrapper or Activity
private var isFullscreen = false
private var playbackPosition = 0L
private var isPlaying = false
private var originalParent: ViewGroup? = null
private var originalLayoutParams: ViewGroup.LayoutParams? = null
private lateinit var fullscreenContainer: FrameLayout

2. Implement Full-Screen Toggle Logic

Add a click listener to your custom controller's fullscreen button to trigger the switch:

fullscreenToggleBtn.setOnClickListener {
    if (isFullscreen) exitFullscreen() else enterFullscreen()
}

Enter Fullscreen

private fun enterFullscreen() {
    isFullscreen = true
    // Save current playback state
    playbackPosition = exoPlayer.currentPosition
    isPlaying = exoPlayer.isPlaying
    exoPlayer.pause()

    // Get your player view (replace with your actual player view reference)
    val playerView = yourCustomPlayerView
    originalParent = playerView.parent as ViewGroup
    originalLayoutParams = playerView.layoutParams

    // Move player to fullscreen container
    originalParent?.removeView(playerView)
    fullscreenContainer.addView(playerView, FrameLayout.LayoutParams(
        ViewGroup.LayoutParams.MATCH_PARENT,
        ViewGroup.LayoutParams.MATCH_PARENT
    ))
    fullscreenContainer.visibility = View.VISIBLE

    // Switch to landscape orientation
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE

    // Hide system UI for immersive fullscreen
    hideSystemUI()

    // Resume playback
    exoPlayer.seekTo(playbackPosition)
    exoPlayer.playWhenReady = isPlaying
}

Exit Fullscreen

private fun exitFullscreen() {
    isFullscreen = false
    // Save current playback state
    playbackPosition = exoPlayer.currentPosition
    isPlaying = exoPlayer.isPlaying
    exoPlayer.pause()

    // Move player back to original container
    val playerView = fullscreenContainer.getChildAt(0) as PlayerView
    fullscreenContainer.removeView(playerView)
    originalParent?.addView(playerView, originalLayoutParams)
    fullscreenContainer.visibility = View.GONE

    // Restore portrait orientation (or your default orientation)
    requestedOrientation = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT

    // Show system UI
    showSystemUI()

    // Resume playback
    exoPlayer.seekTo(playbackPosition)
    exoPlayer.playWhenReady = isPlaying
}

3. Handle System UI Visibility

Implement immersive fullscreen by hiding/showing status and navigation bars:

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
            or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
    window.statusBarColor = Color.TRANSPARENT
    window.navigationBarColor = Color.TRANSPARENT
}

private fun showSystemUI() {
    window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
            or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
            or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION)
    window.statusBarColor = Color.BLACK // Replace with your app's default status bar color
    window.navigationBarColor = Color.BLACK
}

4. Handle Screen Rotation & Lifecycle

Screen rotation will trigger Activity recreation, so save and restore state:

override fun onSaveInstanceState(outState: Bundle) {
    super.onSaveInstanceState(outState)
    outState.putBoolean("isFullscreen", isFullscreen)
    outState.putLong("playbackPosition", playbackPosition)
    outState.putBoolean("isPlaying", isPlaying)
}

override fun onRestoreInstanceState(savedInstanceState: Bundle) {
    super.onRestoreInstanceState(savedInstanceState)
    isFullscreen = savedInstanceState.getBoolean("isFullscreen")
    playbackPosition = savedInstanceState.getLong("playbackPosition")
    isPlaying = savedInstanceState.getBoolean("isPlaying")

    // Re-enter fullscreen if we were in that state before rotation
    if (isFullscreen) enterFullscreen()
}

Extra Tips for RecyclerView/ViewPager

  • Disable scrolling during fullscreen: Set viewPager.isUserInputEnabled = false or recyclerView.layoutManager?.isScrollEnabled = false when entering fullscreen, then re-enable on exit.
  • Player cleanup: When a RecyclerView item or ViewPager page is off-screen, pause and release the player to avoid memory leaks.

5. Final Polish

  • Toggle the fullscreen button's icon (show "shrink" icon when in fullscreen, "expand" otherwise) for better UX.
  • If using PlayerView, leverage its built-in state management, but ensure your custom controller syncs with its state.

This approach works reliably across most use cases—I’ve used it in several apps with nested players. Adjust the code to fit your specific layout and player setup!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 04:22:42