Wrap native ViewController/Fragment
This section provides a guide about how to create a bridge for a native ViewController
(on iOS) and Fragment
(on Android) for Flutter.
It uses AppointmentsFragment
/AppointmentListViewController
as an example, but you can adapt it to any ViewController
/Fragment
of the SDK.
Android
Create the Fragment wrapper
class NablaAppointmentsView(
private val context: Context,
id: Int,
creationParams: Map<String?, Any?>?,
) : PlatformView {
private var view: FragmentContainerView? = null
override fun getView(): View = view ?: kotlin.run {
val fragment = AppointmentsFragment.newInstance()
val viewId = Random().nextInt()
val activity = context.getFragmentActivityOrThrow()
val view = FragmentContainerView(context)
view.setId(viewId)
activity.supportFragmentManager.commit {
replace(viewId, fragment)
}
this.view = view
view
}
override fun dispose() {
view = null
}
private fun Context.getFragmentActivityOrThrow(): FragmentActivity {
if (this is FragmentActivity) {
return this
}
var currentContext = this
while (currentContext is ContextWrapper) {
if (currentContext is FragmentActivity) {
return currentContext
}
currentContext = currentContext.baseContext
}
throw IllegalStateException("Unable to find activity")
}
}
class NablaAppointmentsViewFactory : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
override fun create(context: Context?, viewId: Int, args: Any?): PlatformView {
val creationParams = args as Map<String?, Any?>?
return NablaAppointmentsView(context!!, viewId, creationParams)
}
}
Wire the wrapper
In the MainActivity
file, add these lines to wire your newly created native view:
flutterEngine.platformViewsController
.registry
.registerViewFactory("nablaAppointments", NablaAppointmentsViewFactory())
iOS
Create the ViewController wrapper
class NablaAppointmentsViewFactory : NSObject, FlutterPlatformViewFactory {
private let messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) {
self.messenger = messenger
super.init()
}
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return NablaAppointmentsNativeView(
frame: frame,
viewIdentifier: viewId,
arguments: args,
binaryMessenger: messenger
)
}
}
class NablaAppointmentsNativeView : NSObject, FlutterPlatformView {
private var _viewController: UIViewController
init(
frame: CGRect,
viewIdentifier viewId: Int64,
arguments args: Any?,
binaryMessenger messenger: FlutterBinaryMessenger
) {
_viewController = UIViewController(nibName: nil, bundle: nil)
super.init()
_viewController = NablaSchedulingClient.shared.views.createAppointmentListViewController()
_viewController.view.frame = frame
}
func view() -> UIView {
return _viewController.view
}
}
Wire the wrapper
In the AppDelegate
file, add these lines to wire your newly created view:
weak var registrar = self.registrar(forPlugin: "nabla")
let factory = NablaAppointmentsViewFactory(messenger: registrar!.messenger())
registrar!.register(
factory,
withId: "nablaAppointments"
)
Flutter
Create a file named nablaappointmentswidget.dart
:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter/foundation.dart';
const String viewType = 'nablaAppointments';
Widget _buildAndroid(BuildContext context, Map<String, dynamic> params) {
return AndroidView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: params,
creationParamsCodec: const StandardMessageCodec(),
);
}
Widget _buildIoS(BuildContext context, Map<String, dynamic> params) {
return UiKitView(
viewType: viewType,
layoutDirection: TextDirection.ltr,
creationParams: params,
creationParamsCodec: const StandardMessageCodec(),
);
}
class NablaAppointmentsWidget extends StatelessWidget {
const NablaConversationsWidget({
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
// Pass parameters to the platform side.
final Map<String, dynamic> params = <String, dynamic>{};
switch (defaultTargetPlatform) {
case TargetPlatform.android:
return _buildAndroid(context, params);
case TargetPlatform.iOS:
return _buildIoS(context, params);
default:
throw UnsupportedError('Unsupported platform view');
}
}
}
You can now use the NablaAppointmentsWidget
in your Flutter code.
Updated about 1 month ago