Implementation
Widget builder(BuildContext context, BoxConstraints constraints) {
// get constraints
double height = constraints.maxHeight.isFinite ? constraints.maxHeight : MediaQuery.of(context).size.height;
double width = constraints.maxWidth.isFinite ? constraints.maxWidth : MediaQuery.of(context).size.width;
// set constraints
widget.model.maxHeight = height;
widget.model.maxWidth = width;
// Check if widget is visible before wasting resources on building it
if (!widget.model.visible) return const Offstage();
if (activeDrawer == null) {
fromTop = height;
fromBottom = height;
fromLeft = width;
fromRight = width;
}
top = widget.model.top != null ? BoxView(widget.model.top!) : null;
bottom = widget.model.bottom != null ? BoxView(widget.model.bottom!) : null;
left = widget.model.left != null ? BoxView(widget.model.left!) : null;
right = widget.model.right != null ? BoxView(widget.model.right!) : null;
double screenHeight = height;
double screenWidth = width;
// preset the original dimensions
oldHeight ??= screenHeight;
oldWidth ??= screenWidth;
// check the dimensions for changes, if it has changed, close the any open drawer
if (screenHeight != oldHeight) {
oldHeight = screenHeight;
if (activeDrawer != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
closeDrawer(activeDrawer);
});
}
} else if (screenWidth != oldWidth) {
oldWidth = screenWidth;
if (activeDrawer != null) {
WidgetsBinding.instance.addPostFrameCallback((_) {
closeDrawer(activeDrawer);
});
}
}
// build the child views
List<Widget> children = widget.model.inflate();
if (children.isEmpty) children.add(Container());
BorderRadius drawerHandle = BorderRadius.zero;
if (activeDrawer == Drawers.top) {
visibleDrawer = top;
drawerHandle = widget.model.rounded == false
? BorderRadius.zero
: BorderRadius.only(
topLeft: const Radius.elliptical(0, 0),
topRight: const Radius.elliptical(0, 0),
bottomLeft: Radius.elliptical(
screenWidth * .5,
(screenHeight *
((widget.model.sizeTop != null)
? widget.model.sizeBottom! / screenHeight
: 1)) *
0.05),
bottomRight: Radius.elliptical(
screenWidth * .5,
(screenHeight *
((widget.model.sizeBottom != null)
? widget.model.sizeTop! / screenHeight
: 1)) *
0.05));
} else if (activeDrawer == Drawers.bottom) {
visibleDrawer = bottom;
drawerHandle = widget.model.rounded == false
? BorderRadius.zero
: BorderRadius.only(
topLeft: Radius.elliptical(
screenWidth * .5,
(screenHeight *
((widget.model.sizeBottom != null)
? widget.model.sizeBottom! / screenHeight
: 1)) *
0.05),
topRight: Radius.elliptical(
screenWidth * .5,
(screenHeight *
((widget.model.sizeBottom != null)
? widget.model.sizeBottom! / screenHeight
: 1)) *
0.05),
bottomLeft: const Radius.elliptical(0, 0),
bottomRight: const Radius.elliptical(0, 0));
} else if (activeDrawer == Drawers.left) {
visibleDrawer = left;
drawerHandle = widget.model.rounded == false
? BorderRadius.zero
: BorderRadius.only(
topLeft: const Radius.elliptical(0, 0),
topRight: Radius.elliptical(
screenHeight * 0.05,
(screenWidth *
((widget.model.sizeLeft != null)
? widget.model.sizeLeft! / screenHeight
: 1)) *
.5),
bottomLeft: const Radius.elliptical(0, 0),
bottomRight: Radius.elliptical(
screenHeight * 0.05,
(screenWidth *
((widget.model.sizeLeft != null)
? widget.model.sizeLeft! / screenHeight
: 1)) *
.5));
} else if (activeDrawer == Drawers.right) {
visibleDrawer = right;
drawerHandle = widget.model.rounded == false
? BorderRadius.zero
: BorderRadius.only(
topLeft: Radius.elliptical(
screenHeight * 0.05,
(screenWidth *
((widget.model.sizeRight != null)
? widget.model.sizeRight! / screenHeight
: 1)) *
.5),
topRight: const Radius.elliptical(0, 0),
bottomLeft: Radius.elliptical(
screenHeight * 0.05,
(screenWidth *
((widget.model.sizeRight != null)
? widget.model.sizeRight! / screenHeight
: 1)) *
.5),
bottomRight: const Radius.elliptical(0, 0));
}
double? containerSize(Drawers? drawer) {
if (drawer == Drawers.left) {
return widget.model.sizeLeft ?? screenWidth;
} else if (drawer == Drawers.right) {
return widget.model.sizeRight ?? screenWidth;
} else if (drawer == Drawers.top) {
return widget.model.sizeTop ?? screenHeight;
} else if (drawer == Drawers.bottom) {
return widget.model.sizeBottom ?? screenHeight;
} else {
return screenWidth as bool? ?? 300 < screenHeight
? screenHeight
: screenWidth;
}
}
AnimatedPositioned leftDrawer = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 400 : 0),
onEnd: () => finishedAnimation(),
right: fromRight ?? screenWidth,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onHorizontalDragUpdate: (dragUpdateDetails) =>
onDragging(dragUpdateDetails, DragDirection.horizontal, false),
onHorizontalDragEnd: (dragEndDetails) =>
onDragEnd(dragEndDetails, DragDirection.horizontal, true),
child: ClipRRect(
borderRadius: drawerHandle,
child: SizedBox(
width: ((activeDrawer == Drawers.left || activeDrawer == Drawers.right)
? containerSize(activeDrawer)
: screenWidth),
height: ((activeDrawer == Drawers.top || activeDrawer == Drawers.bottom)
? containerSize(activeDrawer)
: screenHeight),
child:
activeDrawer == Drawers.left ? left ?? Container() : const Offstage()),
),
),
);
AnimatedPositioned rightDrawer = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 400 : 0),
onEnd: () => finishedAnimation(),
left: fromLeft ?? screenWidth,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onHorizontalDragUpdate: (dragUpdateDetails) =>
onDragging(dragUpdateDetails, DragDirection.horizontal, false),
onHorizontalDragEnd: (dragEndDetails) =>
onDragEnd(dragEndDetails, DragDirection.horizontal, true),
child: ClipRRect(
borderRadius: drawerHandle,
child: SizedBox(
width: ((activeDrawer == Drawers.left || activeDrawer == Drawers.right)
? containerSize(activeDrawer)
: screenWidth),
height: ((activeDrawer == Drawers.top || activeDrawer == Drawers.bottom)
? containerSize(activeDrawer)
: screenHeight),
child: activeDrawer == Drawers.right
? right ?? Container()
: const Offstage()),
),
),
);
AnimatedPositioned topDrawer = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 400 : 0),
onEnd: () => finishedAnimation(),
bottom: fromBottom ?? screenHeight,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onVerticalDragUpdate: (dragUpdateDetails) =>
onDragging(dragUpdateDetails, DragDirection.vertical, false),
onVerticalDragEnd: (dragEndDetails) =>
onDragEnd(dragEndDetails, DragDirection.vertical, true),
child: ClipRRect(
borderRadius: drawerHandle,
child: SizedBox(
width: ((activeDrawer == Drawers.left || activeDrawer == Drawers.right)
? containerSize(activeDrawer)
: screenWidth),
height: ((activeDrawer == Drawers.top || activeDrawer == Drawers.bottom)
? containerSize(activeDrawer)
: screenHeight),
child:
activeDrawer == Drawers.top ? top ?? Container() : const Offstage()),
),
),
);
AnimatedPositioned bottomDrawer = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 400 : 0),
onEnd: () => finishedAnimation(),
top: fromTop ?? screenHeight,
child: GestureDetector(
behavior: HitTestBehavior.opaque,
onVerticalDragUpdate: (dragUpdateDetails) =>
onDragging(dragUpdateDetails, DragDirection.vertical, false),
onVerticalDragEnd: (dragEndDetails) =>
onDragEnd(dragEndDetails, DragDirection.vertical, true),
child: ClipRRect(
borderRadius: drawerHandle,
child: SizedBox(
width: ((activeDrawer == Drawers.left || activeDrawer == Drawers.right)
? containerSize(activeDrawer)
: screenWidth),
height: ((activeDrawer == Drawers.top || activeDrawer == Drawers.bottom)
? containerSize(activeDrawer)
: screenHeight),
child: activeDrawer == Drawers.bottom
? bottom ?? Container()
: const Offstage()),
),
),
);
Widget leftHandle = Container();
Widget rightHandle = Container();
Widget topHandle = Container();
Widget bottomHandle = Container();
if (widget.model.handleLeft == true) {
leftHandle = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 500 : 0),
right: (fromRight ?? screenWidth) - 10,
child: SizedBox(
height: screenHeight,
child: Center(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(2)),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Container(
width: 4,
height: 50,
color: Theme.of(context)
.colorScheme
.onSurfaceVariant))))));
}
if (widget.model.handleRight == true) {
rightHandle = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 500 : 0),
left: (fromLeft ?? screenWidth) - 10,
child: SizedBox(
height: screenHeight,
child: Center(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(2)),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Container(
width: 4,
height: 50,
color: Theme.of(context)
.colorScheme
.onSurfaceVariant))))));
}
if (widget.model.handleTop == true) {
topHandle = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 500 : 0),
bottom: (fromBottom ?? screenHeight) - 10,
child: SizedBox(
width: screenWidth,
child: Center(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(2)),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Container(
width: 50,
height: 4,
color: Theme.of(context)
.colorScheme
.onSurfaceVariant))))));
}
if (widget.model.handleBottom == true) {
bottomHandle = AnimatedPositioned(
curve: Curves.easeOutCubic,
duration: Duration(milliseconds: animate ? 500 : 0),
top: (fromTop ?? screenHeight) - 10,
child: SizedBox(
width: screenWidth,
child: Center(
child: ClipRRect(
borderRadius: const BorderRadius.all(Radius.circular(2)),
child: MouseRegion(
cursor: SystemMouseCursors.click,
child: Container(
width: 50,
height: 4,
color: Theme.of(context)
.colorScheme
.onSurfaceVariant))))));
}
var drawer = activeDrawer != null
? GestureDetector(onTap: () => closeDrawer(activeDrawer))
: Container();
Widget view = Stack(children: [
widget.child,
drawer,
leftHandle,
rightHandle,
topHandle,
bottomHandle,
leftDrawer,
rightDrawer,
topDrawer,
bottomDrawer,
]); // view;
// apply user defined constraints
view = applyConstraints(view, widget.model.constraints);
// apply visual transforms
view = applyTransforms(view);
view = GoBack(canGoBack: () async => preventPop(), child: view);
return view;
}