Flutter 中 webview_flutter 4.0 | 基础用法与事件处理


获取页面信息

获取页面 title 信息

核心方法:controller.getTitle 完整示例,放在 main.dart 就能运行。运行示例,点击获取 title 的按钮,会在控制台显示:稀土掘金 使用 WebView_flutter 4.0 主要分三步

  1. 声明 WebViewController
  2. 在 initState 中初始化 controller
  3. 把 controller 赋值给 WebViewWidget,WebViewWidget 显示页面。
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  // 1
  late WebViewController controller;
  
  void initState() {
    // 2
    controller = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..loadRequest(Uri.parse('https://www'));
    super.initState();
  }

  
  Widget build(BuildContext context) {
   
    return MaterialApp(
        home: Scaffold(
            body: Column(
              children: [
                // 3
                Expanded(child: WebViewWidget(controller: controller))
              ],
            ),
            floatingActionButton: ElevatedButton(
              onPressed: () async {
                var title = await controller.getTitle();
                print(title);
              },
              child: Text('获取 title'),
            )));
  }
}

页面信息相关的还有另外三个方法:

  1. currentUrl 获取页面的 url
  2. reload 重新加载当前 url
  3. setUserAgent 设置页面 userAgent

userAgent 用来标识身份。具体怎么写自己定,但要有一个特殊的标识用作区分。比如微信的标识是 MicroMessenger。

滚动页面

  • scrollBy 相对原位置滚动
  • scrollTo 滚动到绝对位置

比如现在滚动位置在 0 0,scrollBy(0,100) 执行一次向下滚动 100,执行两次向下滚动 200。scrollTo(0,100) 执行一次向下滚动 100,执行两次不动,还是在 0 100 的位置。 用 getScrollPosition 可以获得页面当前滚动位置。 这三个都是 controller 的方法和前面提到的 controller.getTitle 的用法是一样的。 虽然 controller 给出了三个方法,但还是略显不够。比如我想让页面向上滚动一半怎么办?还是得靠万能的 js 先获取页面的高度。

floatingActionButton: ElevatedButton(
  onPressed: () async {
    var height = await controller.runJavaScriptReturningResult(
        'document.scrollingElement.scrollHeight') as int;
    var scrollTo = height ~/ 2;
    controller.scrollTo(0, scrollTo);
  },
  child: Text('滚动一半内容'),
)));

当然了,可能无法真正滚动一半内容,这个示例只是为了说明用 controller 的方法不能完成滚动任务时,可以用万能的 js。

WebView 的导航

  • canGoForward
  • canGoBack
  • goForward
  • goBack

前两个判断是否能前进与后退,后两个执行前进与后退。还是比较简单的。这四个都是 controller 上的方法,看名字就知道含意了。

页面来源

加载页面

var controller = WebViewController();
loadRequest(Uri.parse('https://www.enjoysala.top');

添加自定义请求头 用来提供额外的信息。header 的格式

controller.loadRequest(Uri.parse('https://www.enjoysala.top'),headers: {
     "Custom-Name":"IAM17"
});

如果内容过多,需要通过 body 发送。但一看 body 的参数类型傻眼了,是 Uint8List,这是什么鬼? Uint8List 是 8 位无符号整数的固定长度列表。对于长列表,此实现比默认的 List 实现更节省空间和时间。我们理解成用 Uint8List 更高效就行了。那么如何把 String 转成 Uint8List 呢?

import 'dart:typed_data';
Uint8List toUint8List(String str) {

  final List<int> codeUnits = str.codeUnits;
  final unit8List = Uint8List.fromList(codeUnits);
  
  return unit8List;
}


controller.loadRequest(Uri.parse('https://www.enjoysala.top'),
  headers: {
    "Custom-Name": "IAM17",
  },
  method: LoadRequestMethod.post,
  body: toUint8List("我们见过的!"));

 controller
  ..setNavigationDelegate(NavigationDelegate(
    onNavigationRequest: (request) {
      if (request.url.endsWith('/a.html')) {
      
          scheduleMicrotask(() =>
            controller.loadRequest(Uri.parse('http://localhost:8080/b.html'));
          
        return NavigationDecision.prevent;
      }
      return NavigationDecision.navigate;
    },
  ))
  ..loadRequest(Uri.parse('http://localhost:8080'));

页面加载完成事件

NavigationDelegate(
    onPageFinished: (url) async {
      var cookie = await controller
          .runJavaScriptReturningResult('document.cookie') as String;
      print(cookie);
})

Flutter 中 webview_flutter 4.0 | 基础用法与事件处理|获取页面信息|滚动页面|WebView 的导航|页面来源|NavigationDelegate 事件|平易在线