Skip to content

Instantly share code, notes, and snippets.

@jmolins
Forked from slightfoot/bottom_sheet.dart
Created February 18, 2018 23:30
Show Gist options
  • Save jmolins/fcb4f2fbeb0b028165fb311a723563b0 to your computer and use it in GitHub Desktop.
Save jmolins/fcb4f2fbeb0b028165fb311a723563b0 to your computer and use it in GitHub Desktop.
Modal Bottom Sheet with Input Fields fix for Flutter
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
Future<T> showModalBottomSheetApp<T>({
@required BuildContext context,
@required WidgetBuilder builder,
}) {
assert(context != null);
assert(builder != null);
return Navigator.push(context, new _ModalBottomSheetRoute<T>(
builder: builder,
theme: Theme.of(context, shadowThemeOnly: true),
barrierLabel: MaterialLocalizations
.of(context)
.modalBarrierDismissLabel,
));
}
class _ModalBottomSheetRoute<T> extends PopupRoute<T> {
_ModalBottomSheetRoute({
this.builder,
this.theme,
this.barrierLabel,
});
final WidgetBuilder builder;
final ThemeData theme;
@override
Duration get transitionDuration => const Duration(milliseconds: 200);
@override
bool get barrierDismissible => true;
@override
final String barrierLabel;
@override
Color get barrierColor => Colors.black12;
AnimationController _animationController;
@override
AnimationController createAnimationController() {
assert(_animationController == null);
_animationController = BottomSheet.createAnimationController(navigator.overlay);
return _animationController;
}
@override
Widget buildPage(BuildContext context, Animation<double> animation, Animation<double> secondaryAnimation) {
// By definition, the bottom sheet is aligned to the bottom of the page
// and isn't exposed to the top padding of the MediaQuery.
Widget bottomSheet = new MediaQuery.removePadding(
context: context,
removeTop: true,
child: new _ModalBottomSheet<T>(route: this),
);
if (theme != null)
bottomSheet = new Theme(data: theme, child: bottomSheet);
return bottomSheet;
}
}
class _ModalBottomSheet<T> extends StatefulWidget {
const _ModalBottomSheet({ Key key, this.route }) : super(key: key);
final _ModalBottomSheetRoute<T> route;
@override
_ModalBottomSheetState<T> createState() => new _ModalBottomSheetState<T>();
}
class _ModalBottomSheetState<T> extends State<_ModalBottomSheet<T>> {
@override
Widget build(BuildContext context) {
return new AnimatedBuilder(
animation: widget.route.animation,
builder: (BuildContext context, Widget child) {
return new CustomSingleChildLayout(
delegate: new _ModalBottomSheetLayout(MediaQuery.of(context), widget.route.animation.value),
child: new BottomSheet(
animationController: widget.route._animationController,
onClosing: () => Navigator.pop(context),
builder: widget.route.builder
)
);
}
);
}
}
class _ModalBottomSheetLayout extends SingleChildLayoutDelegate {
_ModalBottomSheetLayout(this.data, this.progress);
final MediaQueryData data;
final double progress;
@override
BoxConstraints getConstraintsForChild(BoxConstraints constraints) {
return new BoxConstraints(
minWidth: constraints.maxWidth,
maxWidth: constraints.maxWidth,
minHeight: 0.0,
maxHeight: constraints.maxHeight * 9.0 / 16.0
);
}
@override
Offset getPositionForChild(Size size, Size childSize) {
return new Offset(0.0, size.height - data.viewInsets.bottom - childSize.height * progress);
}
@override
bool shouldRelayout(_ModalBottomSheetLayout oldDelegate) {
return progress != oldDelegate.progress;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment