Flutter中文社区Flutter圈子

FlutterWebViewPlugin

2018-09-04  本文已影响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();
  }
}

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

上一篇下一篇

猜你喜欢

热点阅读