Compose 中使用 WebView

06-01 1426阅读

在 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
                )
                // 设置 WebViewClient
                webViewClient = 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.current
    
    AndroidView(
        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 // 启用JavaScript
                loadUrl(url)
            }
        }
    )
}

带有返回按钮控制的 WebView

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

使用注意事项

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

     
  2. WebView 优化:

    settings.apply {
        javaScriptEnabled = true // 启用JS
        domStorageEnabled = 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 中使用 WebView
    (图片来源网络,侵删)
  • 与 Compose 生命周期完美集成

    2. Compose WebView

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

    Compose 中使用 WebView
    (图片来源网络,侵删)

    添加依赖:

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

    基本用法:

    Compose 中使用 WebView
    (图片来源网络,侵删)
    @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 = """
              

      标题

      这是一个段落

      """ 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 = true
                          domStorageEnabled = true
                      }
                  }
              )
          }
          
          // 监听导航状态
          LaunchedEffect(navigator.canGoBack) {
              canGoBack = navigator.canGoBack
          }
      }

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

免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码