FlutterWebViewPlugin

##简述
在之前对比Flutter和安卓的时候,发现Flutter并没有webview类似的控件,于是一直就在思考要是想在Flutter里面去加载网页应该怎么做呢?流程应该是这样子的,首先一个flutter项目,主入口肯定是dart文件,但是因为flutter没有webview可用来加载网页,所以需要调用安卓原生的webview来加载。这个过程中需要一个plugin来通信。
####原生部分
首先创建一个FlutterPlugin项目,然后在这里写上dart。再然后打开android文件夹,在这里面写上java。然后就完成了。
好了,不扯淡了。说正经的。首先创建一个Flutter Plugin的项目,image
创建好之后在android文件夹下面会有一个FlutterWebviewPlugin(这个是你创建的module名)的java文件。打开是这样子的。

/** FlutterWebviewPlugin */
public class FlutterWebviewPlugin implements MethodCallHandler {
  /** Plugin registration. */
  public static void registerWith(Registrar registrar) {
    final MethodChannel channel = new MethodChannel(registrar.messenger(), "flutter_webview_plugin");
    channel.setMethodCallHandler(new FlutterWebviewPlugin());
  }

  @Override
  public void onMethodCall(MethodCall call, Result result) {
    if (call.method.equals("getPlatformVersion")) {
      result.success("Android " + android.os.Build.VERSION.RELEASE);
    } else {
      result.notImplemented();
    }
  }
}

registerWith是注册插件的方法,一般情况下不要去动他。创建一个构造器,放到setMethodCallHandler(xxx)里面就算是注册成功了。因为这个文件里面主要是实现原生的webview的加载方法,应该都比较熟悉,所以就直接上代码了。
构造器里面的初始代码:

@TargetApi(Build.VERSION_CODES.ECLAIR_MR1)
    public FlutterWebviewPlugin(Activity activity) {
        this.mContext = activity;
        vWebView = new WebView(activity);
        vWebView.getSettings().setJavaScriptEnabled(true);
        vWebView.getSettings().setLoadWithOverviewMode(true);
        vWebView.getSettings().setCacheMode(WebSettings.LOAD_NO_CACHE);
        vWebView.getSettings().setLoadsImagesAutomatically(true);
        vWebView.getSettings().setUseWideViewPort(true);
        vWebView.getSettings().setAllowFileAccess(true);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            vWebView.getSettings().setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);
        }
    }

然后还剩下一个onMethodCall的方法,这个方法就是通信的主要方法。在这里就是dart来通过这个方法,调用java的webview去加载所需要加载的url地址。这里call.method可以自己定义,随便定义成什么都行,也可以定义多个。

@Override
    public void onMethodCall(MethodCall call, Result result) {
        this.result = result;
        switch (call.method) {
            case "loadWeb":
                FrameLayout.LayoutParams params = setupParamsFromFlutter(call);
                LinearLayout linearLayout = new LinearLayout(mContext);
                linearLayout.setOrientation(LinearLayout.VERTICAL);
                final TextView titleView = new TextView(mContext);
                titleView.setTextColor(Color.parseColor("#00000000"));
                ViewGroup.LayoutParams titleViewParams = new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
                        ViewGroup.LayoutParams.MATCH_PARENT);
                titleView.setLayoutParams(titleViewParams);
                titleView.setText("FlutterWebView");
                titleView.setGravity(Gravity.CENTER);
                linearLayout.addView(titleView);
                linearLayout.addView(vWebView);
                mContext.addContentView(linearLayout, params);
                vWebView.setWebViewClient(new MyWebViewClient(mContext, (title, isError) -> titleView.setText(title)));
                vWebView.loadUrl(call.argument("url").toString());
                break;
        }
    }

这里就是创建了一些布局文件,一个标题和一个加载url的webview。都是些常规操作。要说明一点的是,你可能要问我,为什么不在xml里面去写。我当时也是这个想法,context都有了,我写在xml里面再inflate一下不就行了。于是我找了下,结果发现我没有找到可以写布局文件的文件夹。创建的flutter工程里面是没有res这个东西的。因为dart文件的布局是写在dart文件里面的。
####Dart部分
打开lib文件夹,里面有个创建好的文件flutter_webview_plugin.dart。

class FlutterWebviewPlugin {
  static const MethodChannel _channel = const MethodChannel('flutter_webview_plugin');

  static Future<String> get platformVersion async {
    final String version = await _channel.invokeMethod('getPlatformVersion');
    return version;
  }
}

在这里写plugin加载的方法

//声明plugin加载的方法在这里就是launch
//url参数要加载的地址,callback回调,
//可选参数Rect(控制)plugin的大小
Future<Null> launch(
    String url,
    Function callback, {
    Rect rect,
  }) async {
    Map<String, dynamic> args = {
      "url": url,
    };
    if (rect != null) {
      args["rect"] = {
        "left": rect.left,
        "top": rect.top,
        "width": rect.width,
        "height": rect.height
      };
    }
    final String result = await _channel.invokeMethod('load', args);
 
    if (callback != null) {
      callback(result);
    }
  }

然后是main.dart部分,也是就是主要的执行文件,首先我们没有对象,得new一个对象,和java类似,final flutterWebviewPlugin= new FlutterWebviewPlugin();这个名字就是我们上面定义好的插件的名字,拿到对象之后接下来的操作就是调用他里面声明的方法,这一步操作跟java很类似,只是语言是用dart而已。

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_plugin/webview_plugin.dart';
 //主入口MyApp
void main() => runApp(new MyApp());
 
class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return new MaterialApp(
      title: 'Webview',
      theme: new ThemeData(
        //主题颜色
        primarySwatch: Colors.blue,
      ),
      //标题名字,这个随意
      home: new MyHomePage(title: 'Flutter WebView Demo'),
    );
  }
}
 
class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);
 
  final String title;
 
  @override
  _MyHomePageState createState() => new _MyHomePageState();
 
  @override
  initState() {}
}
 
class _MyHomePageState extends State<MyHomePage> {
  StreamSubscription<String> _back;
  var title = "flutter_webview_plugin";
   //webview插件
  final flutterWebviewPlugin= new FlutterWebviewPlugin()
 
  @override
  Widget build(BuildContext context) {
    return new Scaffold(body: new Center(
      //按钮点击事件
      child: new RaisedButton(onPressed: () {
        //拿到flutterwebviewplugin对象,调用他里面的launch方法(我们之前声明过的)
        flutterWebviewPlugin.launch(
            //对应launch方法里面的参数
            "https://www.baidu.com/",
            (data) {
          setState(() {
            title = data;
          });
        },
            rect: new Rect.fromLTWH(0.0, 0.0, MediaQuery.of(context).size.width,
                MediaQuery.of(context).size.height));
      }),
    ));
  }
 
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
  }
}

然后运行上面这个文件,就大功告成啦~

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter 可以通过 `flutter_webview_plugin` 插件来调用 WebView 中的 JavaScript 方法。 首先,在 Flutter 中引入 `flutter_webview_plugin` 插件: ```dart dependencies: flutter_webview_plugin: ^0.3.5+1 ``` 然后在需要使用 WebView 的页面中,导入插件并创建 WebView: ```dart import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; class WebViewPage extends StatefulWidget { @override _WebViewPageState createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> { FlutterWebviewPlugin flutterWebviewPlugin = FlutterWebviewPlugin(); String url = 'https://www.example.com'; @override Widget build(BuildContext context) { return WebviewScaffold( url: url, withJavascript: true, ); } } ``` 在 `WebviewScaffold` 中设置 `withJavascript` 为 `true`,表示开启 WebView 中的 JavaScript 功能。 接下来,可以通过 `evaluateJavascript` 方法来调用 WebView 中的 JavaScript 方法,例如: ```dart flutterWebviewPlugin.evalJavascript('window.alert("Hello, world!")'); ``` 这里调用了 JavaScript 中的 `alert` 方法,弹出一个提示框。 完整的示例代码如下: ```dart import 'package:flutter/material.dart'; import 'package:flutter_webview_plugin/flutter_webview_plugin.dart'; class WebViewPage extends StatefulWidget { @override _WebViewPageState createState() => _WebViewPageState(); } class _WebViewPageState extends State<WebViewPage> { FlutterWebviewPlugin flutterWebviewPlugin = FlutterWebviewPlugin(); String url = 'https://www.example.com'; @override void initState() { super.initState(); flutterWebviewPlugin.onStateChanged.listen((WebViewStateChanged state) { print('onStateChanged: ${state.type} ${state.url}'); }); } @override Widget build(BuildContext context) { return WebviewScaffold( url: url, withJavascript: true, appBar: AppBar( title: Text('WebView'), ), bottomNavigationBar: BottomAppBar( child: Row( mainAxisAlignment: MainAxisAlignment.spaceAround, children: [ IconButton( icon: Icon(Icons.arrow_back), onPressed: () { flutterWebviewPlugin.goBack(); }, ), IconButton( icon: Icon(Icons.arrow_forward), onPressed: () { flutterWebviewPlugin.goForward(); }, ), IconButton( icon: Icon(Icons.refresh), onPressed: () { flutterWebviewPlugin.reload(); }, ), IconButton( icon: Icon(Icons.info), onPressed: () { flutterWebviewPlugin.evalJavascript('window.alert("Hello, world!")'); }, ), ], ), ), ); } } ``` 在底部导航栏中添加了返回、前进、刷新和弹出提示框的按钮,点击弹出提示框时会调用 JavaScript 中的 `alert` 方法。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值