Flutter 中 webview_flutter 4.0 | 基础用法与事件处理
获取页面信息
获取页面 title 信息
核心方法:controller.getTitle 完整示例,放在 main.dart 就能运行。运行示例,点击获取 title 的按钮,会在控制台显示:稀土掘金 使用 WebView_flutter 4.0 主要分三步
- 声明 WebViewController
- 在 initState 中初始化 controller
- 把 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'),
)));
}
}
页面信息相关的还有另外三个方法:
- currentUrl 获取页面的 url
- reload 重新加载当前 url
- 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("我们见过的!"));
NavigationDelegate 事件
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 事件|平易在线