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.mzph.cn/web/78556.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年01月03日美蜥(杭州普瑞兼职)二面

目录 为何 nginx 可以实现跨域请求&#xff0c;原理是什么为何 nodejs 可以实现跨域请求&#xff0c;原理是什么浏览器的请求头有哪些浏览器的响应头有哪些浏览器输入网址后发生什么http 协议和 https 有什么区别你的核心优势是什么浏览器缓存机制https 的加密机制tcp 的三次握…

如何选择合适的光源?

目录 工业相机光源类型全面指南 1. 环形光源及其变体 高角度环形光源 优点 缺点 典型应用场景 低角度环形光源&#xff08;暗场照明&#xff09; 优点 缺点 典型应用场景 2. 条形光源与组合照明系统 技术特点 组合条形光源 优点 缺点 典型应用场景 3. 同轴光源…

「OC」源码学习——对象的底层探索

「OC」源码学习——对象的底层探索 前言 上次我们说到了源码里面的调用顺序&#xff0c;现在我们继续了解我们上一篇文章没有讲完的关于对象的内容函数&#xff0c;完整了解对象的产生对于isa赋值以及内存申请的内容 函数内容 先把_objc_rootAllocWithZone函数的内容先贴上…

【C++指南】STL list容器完全解读(一):从入门到掌握基础操作

. &#x1f493; 博客主页&#xff1a;倔强的石头的CSDN主页 &#x1f4dd;Gitee主页&#xff1a;倔强的石头的gitee主页 ⏩ 文章专栏&#xff1a;《C指南》 期待您的关注 文章目录 一、初识list容器1.1 什么是list&#xff1f;1.2 核心特性1.3 典型应用场景 二、核心成员函数…

labelimg快捷键

一、核心标注快捷键 ‌W‌&#xff1a;调出标注十字架&#xff0c;开始绘制矩形框&#xff08;最常用功能&#xff09;‌A/D‌&#xff1a;切换上一张(A)或下一张(D)图片&#xff0c;实现快速导航‌Del‌&#xff1a;删除当前选中的标注框 二、文件操作快捷键 ‌CtrlS‌&…

linux-文件操作

在 Linux 系统中&#xff0c;文件操作与管理是日常使用和系统管理的重要组成部分。下面将详细介绍文件的复制、移动、链接创建&#xff0c;以及文件查找、文本处理、排序、权限管理等相关知识。 一、文件的复制 在 Linux 里&#xff0c;cp 命令可用于复制文件或目录&#xff…

C++ 复习

VS 修改 C 语言标准 右键项目-属性 输入输出 //引用头文件&#xff0c;用<>包裹起来的一般是系统提供的写好的代码 编译器会在专门的系统路径中去进行查找 #include <iostream> //自己写的代码文件一般都用""包裹起来 编译器会在当前文件所在的目录中査…

openGauss新特性 | HTAP新特性介绍

一、行列融合功能简介 HTAP 行列融合特性在单机、主备场景下&#xff0c;通过节点的行列双格式内存模式&#xff0c;实现openGauss HTAP一体化数据库架构。 通过高效的行列转换技术方案&#xff0c;节点读取磁盘行存数据&#xff0c;生成列存储单元&#xff08;Column Unit&am…

双目测量中的将视差图重投影成三维坐标图

双目测距主要步骤如下&#xff1a; 左右两张图片 → 匹配 → 得到视差图 disp&#xff1b; 使用 cv2.reprojectImageTo3D(disp, Q) 将视差图 重投影 成三维坐标图 → 得到 points_3d 什么是 points_3d&#xff1f; points_3d cv2.reprojectImageTo3D(disp, Q)points_3d.shap…

《深度剖析:SOAP与REST,API集成的两极选择》

API作为不同系统之间交互的桥梁&#xff0c;其设计与实现的优劣直接影响着整个软件生态的运转效率。而在API的设计领域&#xff0c;SOAP和REST犹如两座巍峨的山峰&#xff0c;各自代表着截然不同的设计理念与应用方向&#xff0c;成为开发者在构建API时必须慎重权衡的关键选项。…

非对称加密算法(RSA、ECC、SM2)——密码学基础

对称加密算法&#xff08;AES、ChaCha20和SM4&#xff09;Python实现——密码学基础(Python出现No module named “Crypto” 解决方案) 这篇的续篇&#xff0c;因此实践部分少些&#xff1b; 文章目录 一、非对称加密算法基础二、RSA算法2.1 RSA原理与数学基础2.2 RSA密钥长度…

Pillow 玩图术:轻松获取图片尺寸和颜色模式

前言 在这个“图像为王”的时代,谁还敢说自己没被一张图折磨过?一张图片不讲武德,说崩就崩,说卡就卡,仿佛像素里藏着程序员的眼泪。不管你是网页设计师、AI炼丹师,还是只是想把猫片修得像艺术品,图片的尺寸和颜色模式都是你必须掌握的第一手情报。如果你不知道它有多宽…

下载core5compat 模块时,被禁止,显示 - servese replied: Forbbidden. -->换镜像源

怎么解决&#xff1f; --->换镜像源 方法 1&#xff1a;使用命令行参数指定镜像源 在运行 Qt 安装器时&#xff0c;通过 --mirror 参数指定镜像源&#xff1a; # Windows qt-unified-windows-x64-online.exe --mirror https://mirrors.ustc.edu.cn/qtproject# Linux/macO…

WPF中Behaviors

行为的好处 可以把复杂的界面逻辑抽象出去&#xff0c;让xaml的界面设计更简单&#xff0c;更清爽 1.安装包 Microsoft.Xaml.Behaviors.Wpf2.简单实现拖动效果 <Border Width"100"Height"100"Background"Red"><i:Interaction.Behav…

GitHub 趋势日报 (2025年05月03日)

本日报由 TrendForge 系统生成 https://trendforge.devlive.org/ &#x1f4c8; 今日整体趋势 Top 10 排名项目名称项目描述今日获星总星数语言1hacksider/Deep-Live-Camreal time face swap and one-click video deepfake with only a single image⭐ 1582⭐ 59337Python2aip…

Oracle OCP认证考试考点详解083系列08

题记&#xff1a; 本系列主要讲解Oracle OCP认证考试考点&#xff08;题目&#xff09;&#xff0c;适用于19C/21C,跟着学OCP考试必过。 36. 第36题&#xff1a; 题目 解析及答案&#xff1a; 关于数据库闪回&#xff08;FLASHBACK DATABASE&#xff09;功能&#xff0c;以下…

优化01-统计信息

Oracle 的统计信息是数据库优化器生成高效执行计划的核心依据。它记录了数据库对象&#xff08;如表、索引、列等&#xff09;的元数据信息&#xff0c;帮助优化器评估查询成本并选择最优执行路径。以下是关于 Oracle 统计信息的详细介绍&#xff1a; 一、统计信息的分类 表统…

动态规划-面试题08.01三步问题-力扣(LeetCode)

一、题目解析 此题可以类比第N个泰波那契数 二、算法解析 1、状态表示 根据上面的分析和题目要求&#xff0c;dp[i]表示&#xff1a;到达i位置&#xff0c;一共有多少种方法 2、状态转移方程 以i位置的状态&#xff0c;以最近一步划分问题 dp[i] 从i-1->i dp[i-1] 从…

kotlin中枚举带参数和不带参数的区别

一 ✅ 代码对比总结 第一段&#xff08;带参数 工具方法&#xff09; enum class SeatPosition(val position: Int) {DRIVER_LEFT(0),DRIVER_RIGHT(1),SECOND_LEFT(2),SECOND_RIGHT(3);companion object {fun fromPosition(position: Int): SeatPosition? {return SeatPosi…

Java使用JDBC操作数据库

1.创建一个数据库一会用来连接 2.使用idea新建一个Java项目 3.在pom文件中加上相关依赖&#xff0c;并配置Maven路径 <dependencies><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>…