当前位置: 首页 > backend >正文

Compose 中使用 WebView

在 Jetpack Compose 中,我们可以使用 AndroidView 组件来集成传统的 Android WebView。以下是几种实现方式:

基础 WebView 实现

@Composable
fun WebViewScreen(url: String) {AndroidView(factory = { context ->WebView(context).apply {// 设置布局参数layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,ViewGroup.LayoutParams.MATCH_PARENT)// 设置 WebViewClientwebViewClient = WebViewClient()// 加载网址loadUrl(url)}})
}

增强版 WebView(带更多控制)

@Composable
fun EnhancedWebView(url: String,modifier: Modifier = Modifier,onPageStarted: (String?) -> Unit = {}, // 页面开始加载回调onPageFinished: (String?) -> Unit = {}, // 页面加载完成回调onError: (WebResourceError?) -> Unit = {}, // 加载错误回调onProgressChanged: (Int) -> Unit = {} // 加载进度变化回调
) {val context = LocalContext.currentAndroidView(modifier = modifier,factory = { ctx ->WebView(ctx).apply {webViewClient = object : WebViewClient() {override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {onPageStarted(url)}override fun onPageFinished(view: WebView?, url: String?) {onPageFinished(url)}override fun onReceivedError(view: WebView?,errorCode: Int,description: String?,failingUrl: String?) {onError(WebResourceError(errorCode, description ?: ""))}}webChromeClient = object : WebChromeClient() {override fun onProgressChanged(view: WebView?, newProgress: Int) {onProgressChanged(newProgress)}}settings.javaScriptEnabled = true // 启用JavaScriptloadUrl(url)}})
}

带有返回按钮控制的 WebView

@Composable
fun WebViewWithBackHandler(url: String) {val webView = remember { mutableStateOf<WebView?>(null) }val context = LocalContext.current// 处理返回按钮BackHandler(enabled = webView.value?.canGoBack() == true) {webView.value?.goBack()}AndroidView(factory = { ctx ->WebView(ctx).apply {webView.value = thiswebViewClient = WebViewClient()loadUrl(url)}})
}

使用注意事项

  1. 添加网络权限:在 AndroidManifest.xml 中添加:

    <uses-permission android:name="android.permission.INTERNET" />
  2. WebView 优化

    settings.apply {javaScriptEnabled = true // 启用JSdomStorageEnabled = true // 启用DOM存储cacheMode = WebSettings.LOAD_DEFAULT // 缓存模式
    }
  3. 内存管理:在 Activity 的 onDestroy 中调用 WebView.destroy() 防止内存泄漏

  4. Compose 限制:由于 WebView 是传统 View,某些高级 Compose 功能可能无法直接应用

完整示例使用

@Composable
fun WebViewExample() {var url by remember { mutableStateOf("https://www.example.com") }var loadingProgress by remember { mutableStateOf(0) }var isLoading by remember { mutableStateOf(false) }Column(modifier = Modifier.fillMaxSize()) {// 加载进度条if (isLoading) {LinearProgressIndicator(progress = loadingProgress / 100f,modifier = Modifier.fillMaxWidth())}// WebView 组件EnhancedWebView(url = url,modifier = Modifier.weight(1f),onPageStarted = { isLoading = true },onPageFinished = { isLoading = false },onProgressChanged = { loadingProgress = it },onError = { error -> Toast.makeText(context, "加载错误: ${error.description}", Toast.LENGTH_SHORT).show()})}
}

这样就能在 Compose 应用中完整地集成和使用 WebView 了。

有第三方库支持

Compose 中使用 WebView 的第三方库

在 Jetpack Compose 中,除了使用原生 AndroidView 集成 WebView 外,还有一些优秀的第三方库可以简化 WebView 的使用。以下是几个常用的库:

1. Accompanist WebView (官方推荐)

Google Accompanist 提供的 WebView 库,目前最流行的选择。

添加依赖:

implementation "com.google.accompanist:accompanist-webview:0.34.0"

基本用法:

@Composable
fun WebViewSample() {val state = rememberWebViewState("https://example.com")WebView(state = state,modifier = Modifier.fillMaxSize(),onCreated = { webView ->webView.settings.javaScriptEnabled = true})
}

特性:

  • 内置状态管理 (rememberWebViewState)

  • 支持导航历史

  • 加载进度监听

  • 与 Compose 生命周期完美集成

2. Compose WebView

另一个专门为 Compose 设计的 WebView 库。

添加依赖:

implementation "io.github.kevinnzou:compose-webview:1.6.0"

基本用法:

@Composable
fun WebViewExample() {val webView = rememberWebView()WebView(webView = webView,url = "https://example.com",modifier = Modifier.fillMaxSize(),onPageStarted = { url -> /* 页面开始加载 */ },onPageFinished = { url -> /* 页面加载完成 */ })
}

特性:

  • 更简洁的 API

  • 支持 JavaScript 桥接

  • 内置下载管理器支持

3. Compose Browser

功能更丰富的浏览器组件库。

添加依赖:

implementation "com.moriatsushi.compose:compose-browser:0.1.0"

高级用法:

@Composable
fun BrowserSample() {val controller = rememberBrowserController("https://example.com")Browser(controller = controller,modifier = Modifier.fillMaxSize(),onTitleChanged = { title -> /* 标题变化 */ },onUrlChanged = { url -> /* URL 变化 */ })// 控制导航Button(onClick = { controller.goBack() }) {Text("返回")}
}

4. Compose HTML Viewer

如果只需要显示简单 HTML 内容(不需要完整 WebView 功能)

添加依赖:

implementation "com.github.jeziellago:compose-markdown:0.3.4"

显示 HTML:

@Composable
fun HtmlViewer() {val html = """<h1>标题</h1><p>这是一个段落</p>"""HtmlText(html = html, modifier = Modifier.padding(16.dp))
}

综合比较

库名称优点缺点适用场景
Accompanist WebView官方维护,功能全面API 相对复杂需要完整 WebView 功能
Compose WebViewAPI 简洁,易用功能较少简单 WebView 需求
Compose Browser导航控制方便较新,文档少需要构建浏览器应用
HTML Viewer轻量级仅支持简单 HTML显示静态内容

最佳实践建议

  1. 简单需求:使用 Accompanist WebView

  2. 构建浏览器应用:考虑 Compose Browser

  3. 仅显示内容:HTML Viewer 更轻量

  4. 自定义需求:回退到原生 AndroidView 实现

完整示例(使用 Accompanist):

@Composable
fun FullFeaturedWebView() {var canGoBack by remember { mutableStateOf(false) }val state = rememberWebViewState("https://example.com")val navigator = rememberWebViewNavigator()Column(modifier = Modifier.fillMaxSize()) {// 顶部控制栏Row(verticalAlignment = Alignment.CenterVertically) {IconButton(onClick = { navigator.goBack() },enabled = canGoBack) {Icon(Icons.Default.ArrowBack, "返回")}Text(text = state.pageTitle ?: "加载中...",modifier = Modifier.weight(1f),maxLines = 1,overflow = TextOverflow.Ellipsis)CircularProgressIndicator(progress = state.loadingProgress / 100f,modifier = Modifier.size(24.dp))}// WebView 主体WebView(state = state,navigator = navigator,modifier = Modifier.weight(1f),onCreated = { webView ->webView.settings.apply {javaScriptEnabled = truedomStorageEnabled = true}})}// 监听导航状态LaunchedEffect(navigator.canGoBack) {canGoBack = navigator.canGoBack}
}

这些第三方库可以大大简化在 Compose 中使用 WebView 的复杂度,推荐根据项目需求选择合适的解决方案。

http://www.xdnf.cn/news/4027.html

相关文章:

  • 基于YOLOv的目标检测训练数据构建方法研究—图像采集、标注、划分与增强一体化流程设计
  • Softmax回归与单层感知机对比
  • 【platform push 提示 Invalid source ref: HEAD】
  • 双目视觉的核心目标
  • NGINX 的 ngx_http_auth_jwt_module模块
  • 模块方法模式(Module Method Pattern)
  • JavaScript 实现输入框的撤销功能
  • 算力经济模型推演:从中心化到去中心化算力市场的转变(区块链+智能合约的算力交易原型设计)
  • Python项目源码57:数据格式转换工具1.0(csv+json+excel+sqlite3)
  • C++ 类与对象(下)—— 进阶特性与底层机制解析(构造函数初始化,类型转换,static成员,友元,内部类,匿名对象)
  • 基于 HTML 和 CSS 实现的 3D 翻转卡片效果
  • WebRTC 服务器之SRS服务器概述和环境搭建
  • 【算法笔记】动态规划基础(二):背包dp
  • TopK题-快速选择方法
  • 数据结构实验8.1:图的基本操作
  • 联邦学习的深度解析,有望打破数据孤岛
  • 005-nlohmann/json 基础方法-C++开源库108杰
  • Sim Studio 是一个开源的代理工作流程构建器。Sim Studio 的界面是一种轻量级、直观的方式,可快速构建和部署LLMs与您最喜欢的工具连接
  • 网络安全自动化:找准边界才能筑牢安全防线
  • 数据结构中 数组、链表、图的概念
  • 深入理解CSS盒子模型
  • 如何使用QWidgets设计一个类似于Web Toast的控件?
  • 【Java ee初阶】多线程(5)
  • Electron 架构详解:主进程与渲染进程的协作机制
  • [低代码 + AI] 明道云与 Dify 的三种融合实践方式详解
  • FreeRTOS菜鸟入门(十一)·信号量·二值、计数、递归以及互斥信号量的区别·优先级翻转以及继承机制详解
  • 英伟达语音识别模型论文速读:Token-and-Duration Transducer(TDT)架构
  • Android 控件CalendarView、TextClock用法
  • Notebook.ai 开源程序是一套工具,供作家、游戏设计师和角色扮演者创建宏伟的宇宙 - 以及其中的一切
  • GZ人博会自然资源系统(测绘)备考笔记