Last active
October 7, 2021 09:39
-
-
Save gildaswise/5d1b7bee327a9dd6cc5bcd1bbc72316a to your computer and use it in GitHub Desktop.
A custom implementation of the showModalBottomSheet, with rounded corners
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'; | |
/// Below is the usage for this function, you'll only have to import this file | |
/// [radius] takes a double and will be the radius to the rounded corners of this modal | |
/// [color] will color the modal itself, the default being `Colors.white` | |
/// [builder] takes the content of the modal, if you're using [Column] | |
/// or a similar widget, remember to set `mainAxisSize: MainAxisSize.min` | |
/// so it will only take the needed space. | |
/// | |
/// ```dart | |
/// showRoundedModalBottomSheet( | |
/// context: context, | |
/// radius: 10.0, // This is the default | |
/// color: Colors.white, // Also default | |
/// builder: (context) => ???, | |
/// ); | |
/// ``` | |
Future<T> showRoundedModalBottomSheet<T>({ | |
@required BuildContext context, | |
@required WidgetBuilder builder, | |
Color color = Colors.white, | |
double radius = 10.0, | |
}) { | |
assert(context != null); | |
assert(builder != null); | |
assert(radius != null && radius > 0.0); | |
assert(color != null && color != Colors.transparent); | |
return Navigator.push<T>( | |
context, | |
_RoundedCornerModalRoute<T>( | |
builder: builder, | |
color: color, | |
radius: radius, | |
barrierLabel: | |
MaterialLocalizations.of(context).modalBarrierDismissLabel, | |
)); | |
} | |
class _RoundedModalBottomSheetLayout extends SingleChildLayoutDelegate { | |
_RoundedModalBottomSheetLayout(this.progress); | |
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 - childSize.height * progress); | |
} | |
@override | |
bool shouldRelayout(_RoundedModalBottomSheetLayout oldDelegate) { | |
return progress != oldDelegate.progress; | |
} | |
} | |
class _RoundedCornerModalRoute<T> extends PopupRoute<T> { | |
_RoundedCornerModalRoute({ | |
this.builder, | |
this.barrierLabel, | |
this.color, | |
this.radius, | |
RouteSettings settings, | |
}) : super(settings: settings); | |
final WidgetBuilder builder; | |
final double radius; | |
final Color color; | |
@override | |
Color get barrierColor => Colors.black54; | |
@override | |
bool get barrierDismissible => true; | |
@override | |
String barrierLabel; | |
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) { | |
return MediaQuery.removePadding( | |
context: context, | |
removeTop: true, | |
child: Theme( | |
data: Theme.of(context).copyWith(canvasColor: Colors.transparent), | |
child: AnimatedBuilder( | |
animation: animation, | |
builder: (context, child) => CustomSingleChildLayout( | |
delegate: _RoundedModalBottomSheetLayout(animation.value), | |
child: BottomSheet( | |
animationController: _animationController, | |
onClosing: () => Navigator.pop(context), | |
builder: (context) => Container( | |
decoration: BoxDecoration( | |
color: this.color, | |
borderRadius: BorderRadius.only( | |
topLeft: Radius.circular(this.radius), | |
topRight: Radius.circular(this.radius), | |
), | |
), | |
child: SafeArea(child: Builder(builder: this.builder)), | |
), | |
), | |
), | |
), | |
), | |
); | |
} | |
@override | |
bool get maintainState => false; | |
@override | |
bool get opaque => false; | |
@override | |
Duration get transitionDuration => Duration(milliseconds: 200); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This is now in the pub package rounded_modal.