builder method
Implementation
Widget builder(BuildContext context, BoxConstraints constraints)
{
Log().debug('Build called on framework view => <FML name=${widget.model.templateName} url="${widget.model.url}"/>');
// model is initializing
if (!widget.model.initialized) return Scaffold(body: Center(child: BusyView(BusyModel(null, visible: true))));
// fire navigator change
onNavigatorChange();
// set orientation
String ori = widget.model.orientation ?? 'all';
switch (ori.toLowerCase())
{
case "landscape":
orientation = [DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft];
break;
case "portrait":
orientation = [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown];
break;
case "all":
orientation = [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft];
break;
default:
orientation = [DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, DeviceOrientation.landscapeRight, DeviceOrientation.landscapeLeft];
break;
}
SystemChrome.setPreferredOrientations(orientation);
// set constraints
widget.model.minWidth = constraints.minWidth;
widget.model.maxWidth = constraints.maxWidth;
widget.model.minHeight = constraints.minHeight;
widget.model.maxHeight = constraints.maxHeight;
// build body
List<Widget> children = [];
widget.model.children?.forEach((model)
{
if (model is IViewableWidget) {
children.add((model as IViewableWidget).getView());
}
});
if (children.isEmpty) children.add(Container());
// post onstart callback
if (!started)
{
started = true;
WidgetsBinding.instance.addPostFrameCallback((_) => widget.model.onStart(context));
}
viewportWidth = constraints.maxWidth;
viewportHeight = constraints.maxHeight;
viewportSafeArea = MediaQuery.of(context).padding.top;
// build header model
Widget header = Container();
if (widget.model.header != null && widget.model.header!.visible != false)
{
// setting the min and max heights from the constraint
// sets the height if height is a percentage
widget.model.header!.minHeight = constraints.minHeight;
widget.model.header!.maxHeight = constraints.maxHeight;
// set width && height
headerModel.width = viewportWidth;
headerModel.height = widget.model.header!.height ?? widget.model.header!.maxheight;
// build the header
header = BoxView(headerModel, child: HeaderView(widget.model.header!));
}
else headerModel.height = 0;
// build footer model
Widget footer = Container();
if (widget.model.footer != null && widget.model.footer!.visible != false)
{
widget.model.footer!.minHeight = constraints.minHeight;
widget.model.footer!.maxHeight = constraints.maxHeight;
// set width && height
footerModel.width = viewportWidth;
footerModel.height = widget.model.footer!.height;
footer = BoxView(footerModel, child: FooterView(widget.model.footer!));
}
else footerModel.height = 0;
bodyModel.height = viewportHeight - (headerModel.height ?? 0) - (footerModel.height ?? 0) - viewportSafeArea.ceil();
bodyModel.width = viewportWidth;
Widget body = NotificationListener<ScrollNotification>(onNotification: onScroll, child: BoxView(bodyModel, child: Stack(fit: StackFit.loose, children: children)));
List<Widget> stackChildren = [];
stackChildren.add(header);
stackChildren.add(body);
stackChildren.add(footer);
// We need to provide the stacks children to drawer because positioned
// widgets must be direct children but the drawer uses a builder widget
drawerView = (widget.model.drawer != null) ? DrawerView(widget.model.drawer!, Column(mainAxisSize: MainAxisSize.min, children: [...stackChildren])) : null;
Widget? drawer = drawerView != null ? drawerView : Container();
// primary view
Widget? view = drawerView != null ? drawer : Container(child: SingleChildScrollView( controller: _scrollController, child: Column(mainAxisSize: MainAxisSize.min, children: [...stackChildren])));
// scaffold with safe area
view = SafeArea(child: Scaffold(resizeToAvoidBottomInset: true, body: view));
// simulate a swipe to move back on all desktop applications
// and mobile IOS applications
bool enableSwipeBack = isDesktop || (isMobile && System().useragent == "ios");
final detector = (drawerView != null) ?
GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () => WidgetModel.unfocus(),
onVerticalDragStart: (dragStartDetails) => drawerView!.onDragOpen(dragStartDetails, 'vertical'),
onHorizontalDragStart: (dragStartDetails) => drawerView!.onDragOpen(dragStartDetails, 'horizontal'),
onVerticalDragUpdate: (dragUpdateDetails) => drawerView!.onDragSheet(dragUpdateDetails, 'vertical', true),
onHorizontalDragUpdate: (dragUpdateDetails) => drawerView!.onDragSheet(dragUpdateDetails, 'horizontal', true),
onVerticalDragEnd: (dragEndDetails) => drawerView!.onDragEnd(dragEndDetails, 'vertical', false),
onHorizontalDragEnd: (dragEndDetails) => drawerView!.onDragEnd(dragEndDetails, 'horizontal', false),
onLongPressStart: kDebugMode ? (_) => onLongPressStart() : null,
onLongPressEnd: kDebugMode ? (_) => onLongPressEnd() : null,
child: view)
:
enableSwipeBack ?
GestureDetector(behavior: HitTestBehavior.translucent,
onHorizontalDragStart: onDragStart,
onHorizontalDragEnd: onDragEnd,
onHorizontalDragUpdate: onDragUpdate,
onTap: () => WidgetModel.unfocus(),
onLongPressStart: kDebugMode ? (_) => onLongPressStart() : null,
onLongPressEnd: kDebugMode ? (_) => onLongPressEnd() : null,
child: view) :
GestureDetector(behavior: HitTestBehavior.translucent,
onTap: () => WidgetModel.unfocus(),
onLongPressStart: kDebugMode ? (_) => onLongPressStart() : null,
onLongPressEnd: kDebugMode ? (_) => onLongPressEnd() : null,
child: view);
return detector;
}