FlutterWebViewPlugin

作者: 鸿羽羽羽羽羽 | 来源:发表于2018-09-04 11:43 被阅读33次

    简述

    在之前对比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();
      }
    }
    

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

    相关文章

      网友评论

      本文标题:FlutterWebViewPlugin

      本文链接:https://www.haomeiwen.com/subject/hxrybftx.html