1.7K
Một ví dụ về tạo 2 widget được triển khai dưới Android Native
Dưới Native
Đầu tiên, chúng ta sẽ tạo 2 class FirstWidget.kt và SecondWidget.kt:
- FirstWidget.kt : Sử dụng file .xml
import android.content.Context import android.view.LayoutInflater import android.view.View import io.flutter.plugin.platform.PlatformView internal class FirstWidget(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView { private val view: View override fun getView(): View { return view } init { view = LayoutInflater.from(context).inflate(R.layout.first_widget, null) } override fun dispose() { } }
- first_widget.xml
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" app:layout_behavior="@string/appbar_scrolling_view_behavior" tools:context=".MainActivity" tools:showIn="@layout/first_widget"> <TextView android:id="@+id/first_widget_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="FirstWidget from Android!" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
- SecondWidget.kt: 1 cách khác để tạo view
import android.content.Context import android.graphics.Color import android.view.View import android.widget.TextView import io.flutter.plugin.platform.PlatformView internal class SecondWidget(context: Context, id: Int, creationParams: Map<String?, Any?>?) : PlatformView { private val textView = TextView(context) override fun getView(): View { return textView } override fun dispose() {} init { textView.textSize = 20f textView.setBackgroundColor(Color.rgb(255, 255, 255)) textView.text = "Rendered on a native Android view (id: $id)" } }
Tạo 2 class FirstWidgetFactory.kt và SecondWidgetFactory.kt:
- FirstWidgetFactory.kt
import android.content.Context import io.flutter.plugin.common.StandardMessageCodec import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformViewFactory class FirstWidgetFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) { override fun create(context: Context, viewId: Int, args: Any?): PlatformView { val creationParams = args as Map<String?, Any?>? return FirstWidget(context, viewId, creationParams) } }
- SecondWidgetFactory.kt
import android.content.Context import io.flutter.plugin.common.StandardMessageCodec import io.flutter.plugin.platform.PlatformView import io.flutter.plugin.platform.PlatformViewFactory class SecondWidgetFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) { override fun create(context: Context, viewId: Int, args: Any?): PlatformView { val creationParams = args as Map<String?, Any?>? return SecondWidget(context, viewId, creationParams) } }
Tại MainActivity.kt:
import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine import io.flutter.plugins.GeneratedPluginRegistrant class MainActivity : FlutterActivity() { override fun configureFlutterEngine(flutterEngine: FlutterEngine) { GeneratedPluginRegistrant.registerWith(flutterEngine) flutterEngine .platformViewsController .registry .registerViewFactory("com.example.flutter_app_demo1.FirstWidgetPlugin", FirstWidgetFactory()) flutterEngine .platformViewsController .registry .registerViewFactory("com.example.flutter_app_demo1.SecondWidgetPlugin", SecondWidgetFactory()) } }
Về phần Dart
Tạo 2 file first_widget.dart và second_widget.dart:
- first_widget.dart
import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; class FirstWidget extends StatefulWidget { const FirstWidget({ Key? key, }) : super(key: key); @override State<StatefulWidget> createState() => _FirstWidgetState(); } class _FirstWidgetState extends State<FirstWidget> { String viewType = 'com.example.flutter_app_demo1.FirstWidgetPlugin'; Map<String, dynamic> creationParams = <String, dynamic>{}; @override Widget build(BuildContext context) { if (defaultTargetPlatform == TargetPlatform.android) { return SizedBox( width: 200, child: PlatformViewLink( viewType: viewType, surfaceFactory: (BuildContext context, PlatformViewController controller) { return AndroidViewSurface( controller: controller as AndroidViewController, gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}, hitTestBehavior: PlatformViewHitTestBehavior.opaque, ); }, onCreatePlatformView: (PlatformViewCreationParams params) { return PlatformViewsService.initSurfaceAndroidView( id: params.id, viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), onFocus: () { params.onFocusChanged(true); }, ) ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) ..create(); }, ), ); } return const Text('iOS platform version is not implemented yet.'); } }
- second_widget.dart
import 'package:flutter/foundation.dart'; import 'package:flutter/gestures.dart'; import 'package:flutter/material.dart'; import 'package:flutter/rendering.dart'; import 'package:flutter/services.dart'; class SecondWidget extends StatefulWidget { const SecondWidget({ Key? key, }) : super(key: key); @override State<StatefulWidget> createState() => _SecondWidgetState(); } class _SecondWidgetState extends State<SecondWidget> { String viewType = "com.example.flutter_app_demo1.SecondWidgetPlugin"; Map<String, dynamic> creationParams = <String, dynamic>{}; @override Widget build(BuildContext context) { if (defaultTargetPlatform == TargetPlatform.android) { return PlatformViewLink( viewType: viewType, surfaceFactory: (BuildContext context, PlatformViewController controller) { return AndroidViewSurface( controller: controller as AndroidViewController, gestureRecognizers: const <Factory<OneSequenceGestureRecognizer>>{}, hitTestBehavior: PlatformViewHitTestBehavior.opaque, ); }, onCreatePlatformView: (PlatformViewCreationParams params) { return PlatformViewsService.initSurfaceAndroidView( id: params.id, viewType: viewType, layoutDirection: TextDirection.ltr, creationParams: creationParams, creationParamsCodec: const StandardMessageCodec(), onFocus: () { params.onFocusChanged(true); }, ) ..addOnPlatformViewCreatedListener(params.onPlatformViewCreated) ..create(); }, ); } return const Text('iOS platform version is not implemented yet.'); } }
Sau đó gọi lại 2 Widget vừa rồi tại main.dart
@override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Flutter PlatformView Example'), ), body: Column( mainAxisSize: MainAxisSize.min, mainAxisAlignment: MainAxisAlignment.spaceAround, children: const <Widget>[ Card( child: SizedBox( height: 200, child: FirstWidget(), ), ), Card( child: SizedBox( height: 200, child: SecondWidget(), ), ), ], ), ); }
PlatformView
PlatformView là một tính năng Flutter cần thực hiện để hiển thị Native-UIs toàn diện trên Android View / UIKitView.
Nếu bạn muốn biết thêm thông tin về PlatformView, hãy xem tài liệu chính thức: