AndroidView
Flutter 1.26.0-1.0.pre ,Dart 2.12.0 (build 2.12.0-141.0.dev)
在Flutter小部件上嵌入一個Android的View,與UiKitView對應(yīng),UiKitView是在Flutter小部件上嵌入一個ios的View.
源碼
| 屬性 | 釋義 |
|---|---|
| viewType → String | 這個小部件要嵌入的Android視圖類型的唯一標(biāo)識符。 |
| clipBehavior → Clip | 內(nèi)容被剪輯的方式,默認(rèn)是Clip.hardEdge,在曲線或非軸向直線會呈現(xiàn)鋸齒狀,可以使用Clip.antiAlias |
| creationParams → dynamic | 在PlatformViewFactory調(diào)用create時,作為參數(shù)傳遞 |
| creationParamsCodec → MessageCodec? | 對其進(jìn)行編碼的編解碼器 |
| gestureRecognizers → Set<Factory<OneSequenceGestureRecognizer>>? | 哪些手勢應(yīng)該轉(zhuǎn)發(fā)到Android視圖。 |
| hitTestBehavior → PlatformViewHitTestBehavior | 這個小部件在沖擊測試期間應(yīng)該如何表現(xiàn)。 |
| layoutDirection → TextDirection? | android端view的文字方向 |
| onPlatformViewCreated → PlatformViewCreatedCallback? | 當(dāng)PlatformView創(chuàng)建時的回調(diào) |
示例1 :在Flutter頁面的一個小部件嵌入一個原生的Android視圖。
要實現(xiàn)在Flutter頁面的一個小部件嵌入一個原生的Android視圖,會分為Flutter端和Android端兩端的工作。
我們這里實現(xiàn)在Flutter頁面的一個小部件嵌入一個原生的Android視圖,并可以兩端進(jìn)行通信。Flutter視圖顯示Android端
按鈕被點(diǎn)擊的次數(shù),而Android視圖顯示Flutter端按鈕被點(diǎn)擊的次數(shù),每一次點(diǎn)擊都會立即更新視圖。

android_view.gif
Flutter端需要做的:
- 1.在Flutter的一個小部件中聲明一個AndroidView小部件,并指定AndroidView的viewType.
- 2.在Flutter中聲明通道對象,并設(shè)置監(jiān)聽,當(dāng)Android端調(diào)用通道約定的函數(shù)時,獲取Android端傳來的Android按鈕點(diǎn)擊次數(shù),
并更新Flutter的視圖。 - 3.點(diǎn)擊Flutter按鈕時,通過通道函數(shù)將Flutter按鈕被點(diǎn)擊次數(shù)傳遞給Android端。
Flutter端第一步:在Android端需要注冊PlatformView的工程對象,與Flutter端產(chǎn)生映射關(guān)系,Map<String, PlatformViewFactory> viewFactories,
viewFactories來存儲它們的關(guān)系。
AndroidView(
//與 Android 原生交互時唯一標(biāo)識符,與Android端有對應(yīng)關(guān)系
viewType: 'plugins.flutter.io/android_view',
),
Flutter端第二步:
//創(chuàng)建通道對象,與android端創(chuàng)建的通道對象名稱一致
MethodChannel _channel = MethodChannel("plugins.flutter.io/channel_name_1");
//安卓端的按鈕被點(diǎn)擊的次數(shù)
String _androidButtonClickedNumber = '0';
//當(dāng)前Flutter端按鈕被點(diǎn)擊的次數(shù)
int _flutterButtonClickedNumber = 0;
@override
void initState() {
super.initState();
//設(shè)置此通道上的監(jiān)聽
_channel.setMethodCallHandler(_handlerMethodCall);
}
Future<dynamic> _handlerMethodCall(MethodCall call) async{
//獲取通道監(jiān)聽中調(diào)用的函數(shù)名稱
String method = call.method;
if(method == 'addAndroidButtonAndNoticeFlutter'){
String androidButtonClickedNumber = call.arguments['AndroidButtonClickedNumber'];
_androidButtonClickedNumber = androidButtonClickedNumber;
setState(() {});
}
}
Flutter端第三步:
ElevatedButton(
onPressed: () {
_flutterButtonClickedNumber = _flutterButtonClickedNumber + 1;
setState(() {});
Map<String,String> map = {'FlutterButtonClickedNumber':_flutterButtonClickedNumber.toString()};
//在Flutter端調(diào)用執(zhí)行函數(shù),將Flutter端按鈕的點(diǎn)擊次數(shù)傳遞到安卓端
_channel.invokeMethod("addFlutterButtonAndNoticeAndroid",map);
},
child: Text("+1", style:
TextStyle(fontSize: 18, color: Colors.white),
),
),
Adroid端需要做的:
- 1.聲明一個類MyPlatformView實現(xiàn)PlatformView接口,必須實現(xiàn)getView()函數(shù),這里定義了要顯示的Android視圖。
- 2.聲明一個類MyPlatformViewFactory繼承PlatformViewFactory類,重寫create函數(shù),這里返回上面我們聲明的MyPlatformView。
- 3.聲明一個類MyPlatformViewPlugin實現(xiàn)FlutterPlugin和MethodChannel.MethodCallHandler接口,F(xiàn)lutterPlugin會在
FlutterEngine綁定和解綁的時候產(chǎn)生回調(diào),我們可以在這兩個時機(jī)分別進(jìn)行注冊和注銷的工作。在MyPlatformViewPlugin
中創(chuàng)建通道對象,并監(jiān)聽來自Flutter端的函數(shù)調(diào)用,并進(jìn)行之后的刷新Android視圖。 - 4.將MyPlatformViewPlugin注冊到FlutterEngine
Android端第一步:
public class MyPlatformView implements PlatformView {
private View mNativeView;
private TextView mTvCount;
private Button mBtnAdd;
private int mAndroidButtonClickedNumber = 0;
private MethodChannel mChannel;
public MyPlatformView(Context context, MethodChannel channel) {
mChannel = channel;
mNativeView = LayoutInflater.from(context).inflate(R.layout.view_my_flutter,null,false);
mTvCount = mNativeView.findViewById(R.id.tv_count);
mBtnAdd = mNativeView.findViewById(R.id.btn_add);
mTvCount.setText("Flutter的按鈕被點(diǎn)擊數(shù)量:0");
//點(diǎn)擊安卓按鈕并將安卓按鈕點(diǎn)擊數(shù)量通知Flutter端
mBtnAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mAndroidButtonClickedNumber = mAndroidButtonClickedNumber + 1;
Map<String,String> map = new HashMap<>();
map.put("AndroidButtonClickedNumber",mAndroidButtonClickedNumber+"");
mChannel.invokeMethod("addAndroidButtonAndNoticeFlutter",map);
}
});
}
/**
* 返回嵌入到Flutter頁面中的安卓原生view
* @return
*/
@Override
public View getView() {
return mNativeView;
}
/**
* Flutter的按鈕被點(diǎn)擊數(shù)量+1
* 安卓原生會顯示Flutter的按鈕被點(diǎn)擊的數(shù)量
*/
public void showFlutterButtonClickedNumber(String number){
mTvCount.setText("Flutter的按鈕被點(diǎn)擊數(shù)量:"+number);
}
@Override
public void onFlutterViewAttached(@NonNull View flutterView) { }
@Override
public void onFlutterViewDetached() { }
@Override
public void dispose() { }
}
Android端第二步:
public class MyPlatformViewFactory extends PlatformViewFactory {
private MethodChannel mChannel;
public MyPlatformView mMyPlatformView;
public MyPlatformViewFactory(MessageCodec<Object> createArgsCodec, MethodChannel channel) {
super(createArgsCodec);
mChannel = channel;
}
/**
*
* @param context
* @param viewId 在Flutter端AndroidView的唯一識別id
* @param args Flutter端AndroidView傳遞過來的參數(shù)
* @return
*/
@Override
public PlatformView create(Context context, int viewId, Object args) {
mMyPlatformView = new MyPlatformView(context,mChannel);
return mMyPlatformView;
}
}
Android端第三步:
public class MyPlatformViewPlugin implements FlutterPlugin, MethodChannel.MethodCallHandler {
private MethodChannel mChannel;
private MyPlatformViewFactory mMyPlatformViewFactory;
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
//創(chuàng)建通道對象,通道名稱與Flutter端通道的名稱一致
mChannel = new MethodChannel(binding.getBinaryMessenger(),"plugins.flutter.io/channel_name_1");
//注冊此通道的監(jiān)聽
mChannel.setMethodCallHandler(this);
//創(chuàng)建PlatformView的工廠對象
mMyPlatformViewFactory = new MyPlatformViewFactory(StandardMessageCodec.INSTANCE,mChannel);
//在Flutter引擎上注冊PlatformView的工廠對象
binding.getPlatformViewRegistry()
.registerViewFactory("plugins.flutter.io/android_view",mMyPlatformViewFactory);
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
//注銷通道的監(jiān)聽
mChannel.setMethodCallHandler(null);
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
//獲取監(jiān)聽到的函數(shù)名稱
String methodName = call.method;
if (methodName.equals("addFlutterButtonAndNoticeAndroid")){
String flutterButtonClickedNumber = call.argument("FlutterButtonClickedNumber");
mMyPlatformViewFactory.mMyPlatformView.showFlutterButtonClickedNumber(flutterButtonClickedNumber);
}
}
}
Android端第四步:
public class MainActivity extends FlutterActivity {
@Override
public void configureFlutterEngine(@NonNull FlutterEngine flutterEngine) {
super.configureFlutterEngine(flutterEngine);
//注冊插件
flutterEngine.getPlugins().add(new MyPlatformViewPlugin());
}
}
注:此例子是在純Flutter項目中實現(xiàn)。