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

Jetpack Compose WebView中IFrame视频全屏实现求助

Jetpack Compose WebView IFrame视频全屏实现方案

核心思路

要实现IFrame视频全屏,关键是通过WebChromeClient拦截全屏请求,切换Compose布局显示视频视图;同时配置WebView的基础参数,确保视频能触发全屏逻辑。

具体实现步骤

  1. 配置WebView基础参数
    开启JavaScript、允许媒体播放相关权限,这些是视频全屏的前提:
webView.settings.apply {
    javaScriptEnabled = true
    domStorageEnabled = true
    mediaPlaybackRequiresUserGesture = false // 按需开启,允许视频自动播放
    allowFileAccess = true
    setSupportZoom(false)
    builtInZoomControls = false
    displayZoomControls = false
}
  1. 自定义WebChromeClient处理全屏逻辑
    实现onShowCustomView和onHideCustomView方法,这两个方法会在视频进入/退出全屏时被调用,我们需要在这里更新全屏状态并处理系统UI:
private inner class CustomWebChromeClient(
    private val onFullScreenChanged: (Boolean, View?) -> Unit
) : WebChromeClient() {
    private var customViewCallback: CustomViewCallback? = null

    override fun onShowCustomView(view: View?, callback: CustomViewCallback?) {
        super.onShowCustomView(view, callback)
        customViewCallback = callback
        onFullScreenChanged(true, view)
        // 隐藏系统状态栏和导航栏,实现沉浸式全屏
        requireActivity().window.decorView.systemUiVisibility = (
                View.SYSTEM_UI_FLAG_FULLSCREEN
                or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                )
    }

    override fun onHideCustomView() {
        super.onHideCustomView()
        customViewCallback?.onCustomViewHidden()
        onFullScreenChanged(false, null)
        // 恢复系统UI显示
        requireActivity().window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
    }
}
  1. Compose布局中集成WebView与全屏视图
    用remember保存全屏状态和视频视图,根据状态切换显示WebView还是全屏视频:
@Composable
fun WebViewScreen(onFullScreenChanged: (Boolean) -> Unit) {
    var isFullScreen by remember { mutableStateOf(false) }
    var fullScreenView by remember { mutableStateOf<View?>(null) }

    LaunchedEffect(isFullScreen) {
        onFullScreenChanged(isFullScreen)
    }

    if (isFullScreen && fullScreenView != null) {
        // 全屏状态下仅显示视频视图
        AndroidView(factory = { fullScreenView!! })
    } else {
        // 非全屏状态显示WebView
        AndroidView(
            factory = { context ->
                WebView(context).apply {
                    webChromeClient = CustomWebChromeClient { fullScreen, view ->
                        isFullScreen = fullScreen
                        fullScreenView = view
                    }
                    settings.apply {
                        javaScriptEnabled = true
                        domStorageEnabled = true
                        mediaPlaybackRequiresUserGesture = false
                        allowFileAccess = true
                        setSupportZoom(false)
                        builtInZoomControls = false
                        displayZoomControls = false
                    }
                    // 加载包含IFrame的页面,替换为你的实际内容
                    loadData(
                        "<html><body><iframe width='100%' height='300' src='https://www.youtube.com/embed/your-video-id' frameborder='0' allow='autoplay; fullscreen'></iframe></body></html>",
                        "text/html",
                        "utf-8"
                    )
                }
            }
        )
    }
}
  1. 处理返回键退出全屏
    在MainActivity中重写返回逻辑,优先退出全屏再处理页面返回:
class MainActivity : ComponentActivity() {
    private var isFullScreen by mutableStateOf(false)

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            YourAppTheme {
                WebViewScreen(onFullScreenChanged = { isFullScreen = it })
            }
        }

        onBackPressedDispatcher.addCallback(this) {
            if (isFullScreen) {
                isFullScreen = false
                window.decorView.systemUiVisibility = View.SYSTEM_UI_FLAG_VISIBLE
                this.isEnabled = false
                onBackPressedDispatcher.onBackPressed()
            } else {
                finish()
            }
        }
    }
}

崩溃问题排查

如果集成后出现崩溃,大概率是以下原因:

  • 空指针异常:onShowCustomView中view为空,需添加非空判断;
  • 视图重复添加:全屏视图未正确从父容器移除,可在onHideCustomView中调用fullScreenView?.parent?.let { (it as ViewGroup).removeView(fullScreenView) };
  • 配置变化丢失状态:用rememberSaveable替代remember保存isFullScreen状态(View无法直接序列化,仅保存状态标记即可)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.12 11:05:04