Flutter -- Flutter嵌入Native组件

上一篇文章写了怎么在Flutter中调用Native的方法,同时Flutter也提供了嵌入原生Native组件的方法

###1、创建一个插件
在android studio中创建了一个Flutter Plugin。这里直接在一个Flutter项目中创建了一个Plugin,主要尝试使用本地依赖的方式引入
图1

#####这里遇到了一个坑,我创建完了一个插件之后,AS卡死了, 随后我在项目的根目录下执行了flutter packages get 之后, 并重启IDE之后才解决

###2、解决报错
我在一个Flutter项目中创建了一个本地的Plugin,项目结构大概是这个样子,但是有报错。是插件中的测试文件找不到Flutter相关的包,我在插件的pubspec.yaml加入一行,如下图3, get packages 之后发现只有找不到MyApp了,我确实没有MyApp,删掉就好。

图2
图3

图4

###3、编写Android代码
还是在Android端编写代码(因为我根本不会ios),Android端代码也有报错,是找不到Flutter相关的jar包,我用了好多种方式,最后,直接用AS打开了插件下的example中的android项目。
长时间build之后,项目没有报错,开了两个AS,除了风扇有点响之外没有其他的异常出现。
图5
图6

###4、关联主项目
在主项中的配置文件添加插件的本地路径,然后flutter packages get
图7

到此位置、配置工作已经完成了,接下来就可以写代码了

###5、创建Native组件
首先在远端创建一个view,这个我们需要Flutter提供的PlatformViewFactory

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
class WebViewPlatformViewFactory extends PlatformViewFactory implements MethodChannel.MethodCallHandler {
private WebView mWebView;
private PluginRegistry.Registrar mRegistrar;

WebViewPlatformViewFactory(PluginRegistry.Registrar registrar) {
super(StandardMessageCodec.INSTANCE);
mRegistrar = registrar;
}

@Override
public PlatformView create(final Context context, int id, Object o) {
final MethodChannel channel = new MethodChannel(mRegistrar.messenger(), "webview_plugin_" + id);
channel.setMethodCallHandler(this);

mWebView = new WebView(mRegistrar.context());
mWebView.setWebViewClient(new WebViewClient());

return new PlatformView() {
@Override
public View getView() {
return mWebView;
}

@Override
public void dispose() {

}
};
}

@Override
public void onMethodCall(MethodCall methodCall, MethodChannel.Result result) {
String method = methodCall.method;
switch (method) {
case "loadUrl":
mWebView.loadUrl(methodCall.arguments.toString());
result.success(null);
break;
default:
result.notImplemented();
break;
}

}
}
  • PlatformViewFactory 用于创建跨平台的视图
  • MethodChannel 用于消息通讯
  • PlatformView 向Flutter返回一个Native组件

###6、创建Flutter组件
在Flutter端封装一个叫webview的组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class WebView extends StatefulWidget {
final ControllerCallBack controller;

WebView({Key key, this.controller}) : super(key: key);

@override
_WebViewState createState() => _WebViewState();
}

class _WebViewState extends State<WebView> {

@override
Widget build(BuildContext context) {
return Container(
child: AndroidView(
onPlatformViewCreated: _onPlatformViewCreated,
creationParamsCodec: StandardMessageCodec(),
viewType: "org.tiny.webviewplugin.webview",
),
);
}

void _onPlatformViewCreated(int id) {
_WebViewController controller = _WebViewController._(id);
widget.controller(controller);
}
}

class _WebViewController {
MethodChannel _channel;

_WebViewController._(int id) {
_channel = MethodChannel('webview_plugin_$id');
}

void loadUrl(String url) async {
await _channel.invokeMethod("loadUrl", url);
}
}

typedef ControllerCallBack = Function(_WebViewController controller);

  • onPlatformViewCreated 当view创建完成时调用,在这之后我们才能建立消息通道,调用远程视图

###7、注册组件
Android 端进行组件的注册

1
2
3
4
5
6
7
8
public class WebviewPlugin {
/** Plugin registration. */
public static void registerWith(Registrar registrar) {

registrar.platformViewRegistry().registerViewFactory("org.tiny.webviewplugin.webview",
new WebViewPlatformViewFactory(registrar));
}
}

  • WebviewPlugin 其实是主项目引入这个插件时, 主项目就会自动的去调用WebviewPlugin 的 registerWith 方法,这个类是自动生成的。
    图8

###8、
Android端显示的webview组件

图9

###9、问题
点击input框,软件盘不会弹出

·