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

如何在Jetpack Compose的Media3 ExoPlayer中移除进度条及15秒进退按钮

在Jetpack Compose中自定义Media3 ExoPlayer直播控制视图

先修正你当前代码里的几个基础问题:

  • video: string? 需改为 video: String?(Kotlin中类型首字母大写)
  • 判空逻辑里的videoUri应替换为video,与函数参数保持一致
  • 异常抛出建议用更规范的IllegalArgumentException

修正后的基础代码:

@Composable
fun VideoView(video: String?, viewModel: ChannelsViewModel = viewModel()) {
    val context = LocalContext.current
    if (video == null) {
        throw IllegalArgumentException("Video URI cannot be null")
    }
    val exoPlayer = ExoPlayer.Builder(context)
        .build()
        .also { exoPlayer ->
            val mediaItem = MediaItem.Builder()
                .setUri(video)
                .build()
            exoPlayer.setMediaItem(mediaItem)
            exoPlayer.prepare()
            exoPlayer.playWhenReady = true
        }

    DisposableEffect(exoPlayer) {
        val listener = object : Player.Listener {
            // 后续添加直播状态判断逻辑
        }
        exoPlayer.addListener(listener)
        onDispose {
            exoPlayer.removeListener(listener)
            exoPlayer.release()
        }
    }

    AndroidView(factory = {
        PlayerView(context).apply {
            player = exoPlayer
            layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
            // 此处添加自定义控制器配置
        }
    })
}

以下是两种实现直播模式下隐藏进度条和15秒进退按钮的方案:

方案一:自定义控制器布局XML

这种方式可以完全掌控控制视图的结构:

  1. 在res/layout目录下创建custom_live_player_controller.xml,复制Media3默认控制器布局(可从Media3库的layout/exo_player_control_view.xml获取原布局),然后删除以下组件:

    • 进度条(id为exo_progress的ProgressBar)
    • 15秒后退按钮(id为exo_rew的ImageButton)
    • 15秒前进按钮(id为exo_ffwd的ImageButton)
  2. 在PlayerView中设置自定义布局:

AndroidView(factory = { ctx ->
    PlayerView(ctx).apply {
        player = exoPlayer
        layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
        // 绑定自定义控制器布局
        controllerLayoutId = R.layout.custom_live_player_controller
    }
})

方案二:代码动态隐藏指定组件

如果不想自定义XML,可通过代码定位默认控制器的子视图,根据直播状态动态切换显示:

// 先通过remember持有PlayerView引用
val playerView = remember { mutableStateOf<PlayerView?>(null) }

DisposableEffect(exoPlayer) {
    val listener = object : Player.Listener {
        override fun onTimelineChanged(timeline: Timeline, reason: Int) {
            super.onTimelineChanged(timeline, reason)
            playerView.value?.let { updateControllerVisibility(exoPlayer, it) }
        }
    }
    exoPlayer.addListener(listener)
    onDispose {
        exoPlayer.removeListener(listener)
        exoPlayer.release()
    }
}

AndroidView(factory = { ctx ->
    PlayerView(ctx).apply {
        player = exoPlayer
        layoutParams = FrameLayout.LayoutParams(MATCH_PARENT, MATCH_PARENT)
        playerView.value = this
    }
})

// 辅助函数:根据直播状态控制组件显示
private fun updateControllerVisibility(player: ExoPlayer, playerView: PlayerView) {
    val isLive = player.currentTimeline.windowCount > 0 && 
                 player.currentTimeline.getWindow(0, Timeline.Window()).isLive
    playerView.post {
        // 隐藏/显示15秒进退按钮
        playerView.findViewById<ImageButton>(R.id.exo_rew)?.visibility = if (isLive) View.GONE else View.VISIBLE
        playerView.findViewById<ImageButton>(R.id.exo_ffwd)?.visibility = if (isLive) View.GONE else View.VISIBLE
        // 隐藏/显示进度条
        playerView.findViewById<ProgressBar>(R.id.exo_progress)?.visibility = if (isLive) View.GONE else View.VISIBLE
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.19 18:33:15