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:

Leave a Reply