Merge pull request #1850 from HansMuller/bottom_sheet_drag

Support dismissing the modal bottom sheet with a drag gesture
This commit is contained in:
Hans Muller 2015-10-28 13:13:44 -07:00
commit b86c150184

View File

@ -13,6 +13,8 @@ import 'colors.dart';
import 'material.dart';
const Duration _kBottomSheetDuration = const Duration(milliseconds: 200);
const double _kMinFlingVelocity = 700.0;
const double _kFlingVelocityScale = 1.0 / 300.0;
class _BottomSheet extends StatefulComponent {
_BottomSheet({
@ -22,7 +24,7 @@ class _BottomSheet extends StatefulComponent {
}) : super(key: key);
final Widget child;
final PerformanceView performance;
final Performance performance;
_BottomSheetState createState() => new _BottomSheetState();
}
@ -49,6 +51,26 @@ class _BottomSheetLayout extends OneChildLayoutDelegate {
class _BottomSheetState extends State<_BottomSheet> {
final _BottomSheetLayout _layout = new _BottomSheetLayout();
bool _dragEnabled = false;
void _handleDragStart(Point position) {
_dragEnabled = !config.performance.isAnimating;
}
void _handleDragUpdate(double delta) {
if (!_dragEnabled)
return;
config.performance.progress -= delta / _layout.childTop.end;
}
void _handleDragEnd(Offset velocity) {
if (!_dragEnabled)
return;
if (velocity.dy > _kMinFlingVelocity)
config.performance.fling(velocity: -velocity.dy * _kFlingVelocityScale);
else
config.performance.forward();
}
Widget build(BuildContext context) {
return new BuilderTransition(
@ -59,7 +81,12 @@ class _BottomSheetState extends State<_BottomSheet> {
child: new CustomOneChildLayout(
delegate: _layout,
token: _layout.childTop.value,
child: new Material(child: config.child)
child: new GestureDetector(
onVerticalDragStart: _handleDragStart,
onVerticalDragUpdate: _handleDragUpdate,
onVerticalDragEnd: _handleDragEnd,
child: new Material(child: config.child)
)
)
);
}
@ -67,12 +94,17 @@ class _BottomSheetState extends State<_BottomSheet> {
}
}
class _ModalBottomSheetRoute extends PerformanceRoute {
_ModalBottomSheetRoute({ this.completer, this.child });
class _ModalBottomSheetRoute extends Route {
_ModalBottomSheetRoute({ this.completer, this.child }) {
_performance = new Performance(duration: transitionDuration, debugLabel: 'ModalBottomSheet');
}
final Completer completer;
final Widget child;
PerformanceView get performance => _performance?.view;
Performance _performance;
bool get ephemeral => true;
bool get modal => true;
bool get opaque => false;
@ -93,7 +125,7 @@ class _ModalBottomSheetRoute extends PerformanceRoute {
),
// sheet
new _BottomSheet(
performance: performance,
performance: _performance,
child: child
)
])
@ -101,9 +133,16 @@ class _ModalBottomSheetRoute extends PerformanceRoute {
);
}
void didPush(NavigatorState navigator) {
super.didPush(navigator);
_performance?.forward();
}
void didPop([dynamic result]) {
completer.complete(result);
super.didPop(result);
if (_performance.status != PerformanceStatus.dismissed)
_performance?.reverse();
}
}