-
-
Save jmolins/fcb4f2fbeb0b028165fb311a723563b0 to your computer and use it in GitHub Desktop.
Modal Bottom Sheet with Input Fields fix for Flutter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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