Flutter: el uso de WebView y la interacción con JS

El uso de WebView es relativamente común, especialmente la interacción con JS. Hoy, resolveré algunas cosas sobre el uso de WebView en flutter ~ Concéntrese en el
uso de los siguientes dos complementos principales:

Complemento oficial: webview_flutter
pub Complemento más útil: flutter_webview_plugin

El uso de cualquier complemento es un proceso de dos pasos:
1. Importar dependencias
2. Importar y usar componentes de la aplicación (widgets)

Sin embargo, durante el uso de este complemento, se debe configurar un elemento separado en IOS; de lo contrario, se informará un error. De la siguiente manera, agregue ios/Runner/Info.plist

1
2

<key>io.flutter.embedded_views_preview</key>
<string>SÍ</string>*

Este artículo se enfoca primero en practicar el uso de complementos oficiales.
Para facilitar la distinción, el uso de los dos complementos se coloca en un archivo dart, de la siguiente manera:

class WidgetWebview extends StatefulWidget {
  String remoteUrl = "https://www.baidu.com";
  String localUrl = "assets/html/login.html";
  bool useWebviewFlutter = true; // 是否使用 flutter 提供的插件

  @override
  _WidgetWebviewState createState() =>
      useWebviewFlutter ? _WebviewFlutterState() : _FlutterWebViewPluginState();
}
/// 方便将两个插件放在一起对比~
abstract class _WidgetWebviewState extends State<WidgetWebview> {}

class _WebviewFlutterState extends _WidgetWebviewState {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("WebViewFlutter 与 JS 交互"),
      ),
    );
  }
}

class _FlutterWebViewPluginState extends _WidgetWebviewState {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("FlutterWebViewPlugin 与 JS 交互"),
      ),
    );
  }
}

Entonces este artículo   procesará _WebviewFlutterState

uso básico

En ios, agréguelo en ios/Runner/Info.plist  o la página no se cargará...

1
2

<key>io.flutter.embedded_views_preview</key>
<string>SÍ</string>*

Primero use WebView para cargar una página, es muy simple, solo  agregue el  componente WebView en el  método  build() , el siguiente es su constructor

  const WebView({
    Key key,
    this.onWebViewCreated, //WebView 创建完成之后的回调
    this.initialUrl, // 初始化 URL
    this.javascriptMode = JavascriptMode.disabled, // JS执行模式 默认是不调用
    this.javascriptChannels, // JS可以调用Flutter 的通道
    this.navigationDelegate, // 路由委托(可以通过在此处拦截url实现JS调用Flutter部分) 拦截 URL
    this.gestureRecognizers, // 手势相关
    this.onPageFinished, // 页面加载完成的回调
    this.debuggingEnabled = false,
    this.userAgent,
    this.initialMediaPlaybackPolicy =
        AutoMediaPlaybackPolicy.require_user_action_for_all_media_types,
  })

De hecho, a través de una simple comprensión del constructor, básicamente aprendí cómo usarlo, entonces, ¿cómo cargar una URL de la manera más simple?

     body: WebView(
        initialUrl: widget.remoteUrl,
      ),

 

¿No es muy simple?Este es el uso más simple para cargar una página.

uso avanzado

Lo anterior decía cómo simplemente cargar una página, luego habrá otros usos que se pueden usar ~
WebView tiene un controlador llamado  WebViewController , que se usa para manejar algunas cosas, y se puede   obtener en WebView.onWebViewCreated .

Obtener el título de la página

Muchas veces, es necesario mostrar el título de la barra de aplicaciones de la página flutter actual como título en la página web, entonces, ¿cómo obtener este título? El WebViewController mencionado anteriormente tiene un  método getTitle()  , que se puede usar para obtener el título de la página web, de la siguiente manera:

  /// 获取当前加载页面的 title
  _getTitle() async {
    String title = await _webViewController.getTitle();
    print("title---$title");
  }

 

Obtenga la cadena de título desde aquí y luego podrá usarla para el procesamiento.

Cargue un archivo HTML local

Cargue directamente el código, los puntos que deben tenerse en cuenta son:
1. Bundle.loadString() se ejecuta de forma asíncrona, por lo que debe usar FutureBuilder para procesar el componente de inmediato.
2. Use Uri para transcodificar el archivo, como se muestra en el código
3. Al agregar dependencias a los archivos locales, ¡preste atención a la precisión de la ruta! Aquí creé un directorio html en mi directorio de activos y puse el archivo HTML aquí, por lo que se debe usar la ruta html específica en la dependencia.

1
2
3

  activos:
    - activos/
    - activos/html/

 @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: FutureBuilder(
        future: _loadHtmlFile(),
        builder: (context, snapshot) {
          return WebView(
            initialUrl: Uri.dataFromString(snapshot.data, mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
                      .toString(),
            onWebViewCreated: (WebViewController controller) {
              print("webview page: webview created...");
              _webViewController = controller;
              _webViewController.loadUrl(
                  new Uri.dataFromString(snapshot.data, mimeType: 'text/html', encoding: Encoding.getByName('utf-8'))
                      .toString());
            },
            onPageFinished: (url) {
              print("webview page: load finished...url=$url");
              _getTitle();
            },
          );
        },
      ),
    );
  }

 

JS llama al método flutter

Aquí viene lo más destacado, llame al método en flutter en HTML. Como se mencionó anteriormente, hay dos formas en que JS puede llamar a Flutter: use javascriptChannels  para enviar mensajes y use el delegado de enrutamiento navigationDelegate  para interceptar la URL para lograr la interacción.
No hablaré sobre la implementación de la interceptación por el momento. Personalmente, creo que es bastante insípido. Los amigos interesados ​​​​pueden estudiarlo por sí mismos (risas...)

Enviar mensajes usando javascriptChannels

El parámetro javascriptChannels tiene la forma de una matriz, lo que significa que se puede crear un objeto correspondiente (JavascriptChannel) para que cada método interactúe y se arroje a la matriz. Pero creo que también es posible considerar crear un objeto y luego usar las claves en JavascriptChannel para distinguir el procesamiento, pero no es posible por el momento, porque solo hay un parámetro en JavascriptMessage, que sigue siendo un tipo de cadena, por lo que no es fácil de manejar. . . Este artículo usa el primer método.
Por ejemplo, ahora quiero llamar a un método de brindis flutter en js para mostrar un brindis, luego el primer paso es crear un JavascriptChannel de la siguiente manera:

  // 创建 JavascriptChannel
  JavascriptChannel _toastJsChannel(BuildContext context) => JavascriptChannel(
      name: 'show_flutter_toast',
      onMessageReceived: (JavascriptMessage message) {
        print("get message from JS, message is: ${message.message}");
        T.show(message.message);
      });

 

1

javascriptChannels: [_toastJsChannel(contexto)].toSet(),

Los puntos a explicar son:
1. El parámetro nombre corresponde a una clave de tipo String, que es como se llama en JS (postMessage(“xxx”)), y debe ser consistente.
2. onMessageReceived devuelve la llamada a un objeto JavascriptMessage para recibir información de devolución de llamada de JS. Actualmente solo hay un atributo de mensaje (String). Solo se admiten parámetros de tipo String. Si hay demasiados datos, puede considerar los parámetros de tipo String JSON.
El siguiente paso es escribir código JS simple ~~

<div class = "rect" style="margin-top: 50px;" onclick="flutterShowToast()">JS调用Flutter</div>

  /// 调用 flutter 的方法
  /// -name:show_flutter_toast
  function flutterShowToast() {
    show_flutter_toast.postMessage("message from JS...");
  }

 

El código en el HTML es muy simple. Se trata de establecer un evento de clic para un div y ajustar el método de flutterShowToast. ¡Una cosa a la que se debe prestar especial atención es que show_flutter_toast no debe escribirse  mal! (Debería saber por qué esta cadena debe usarse aquí ~)

Flutter llama a JS

Después de crear el WebView, podemos obtener un WebViewController y, a través de su método de evaluaciónJavascript(), podemos ejecutar instrucciones JS.

WebViewController _webViewController;
...
onWebViewCreated: (WebViewController controller) {
              print("webview page: webview created...");
              _webViewController = controller;
              _webViewController.loadUrl(new Uri.dataFromString(snapshot.data,
                      mimeType: 'text/html',
                      encoding: Encoding.getByName('utf-8'))
                  .toString());
            }
...
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.add),
        onPressed: (){
          _webViewController.evaluateJavascript("flutterCallJsMethod('message from Flutter!')");
        },
      ),

El evento de transferencia se activa al agregar un FloatingActionButton en la página. Como se mencionó anteriormente, se llama al método de evaluación Javascript, el contenido es el método y los parámetros en JS, y luego se escribe una función correspondiente con el mismo nombre en el HTML para realizar el pasó la transición de flutter a jS, el código HTML es el siguiente:

  /// Flutter 调用 JS 的此方法
  /// 在 Flutter 中通过 _webViewController.evaluateJavascript("flutterCallJsMethod('message from Flutter!')") 调用
  function flutterCallJsMethod(message) {
      document.getElementById("show_info").innerText = message;
  }

 

Al mismo tiempo, evaluarJavascript devuelve un objeto Future, que se puede usar para hacerse cargo del contenido devuelto por JS.
Nota: el método de evaluaciónJavascript() **, Flutter recomienda que lo ejecutemos después de la devolución de llamada onPageFinished para garantizar que todo el HTML se haya cargado. Por lo tanto, en el desarrollo real, se recomienda consultar mi método de escritura y poner WebView en FutureBuilder~

Supongo que te gusta

Origin blog.csdn.net/qq_27909209/article/details/130412141
Recomendado
Clasificación