Flutter: Custom Draggable Bottom Sheet

Layout

import 'package:flutter/material.dart';

class Main extends StatefulWidget {
const Main({Key? key}) : super(key: key);

@override
State<Main> createState() => _MainState();
}

class _MainState extends State<Main> {
final double _headerHeight = 40.0;
final double _maxHeight = 600.0;
bool _isDragUp = true;
double _bodyHeight = 0.0;

@override
Widget build(BuildContext context) {
final Size _size = MediaQuery.of(context).size;

return Scaffold(
body: Stack(
children: <Widget>[
Center(child: Text("Custom Scrollable Bottom Sheet ")),
Positioned(
bottom: 0.0,
child: AnimatedContainer(
constraints: BoxConstraints(
maxHeight: this._maxHeight,
minHeight: this._headerHeight,
),
curve: Curves.easeOut,
height: this._headerHeight,
duration: const Duration(milliseconds: 600),
child: GestureDetector(
onVerticalDragUpdate: (DragUpdateDetails data) {

},
onVerticalDragEnd: (DragEndDetails data){

},
child: Column(
children: <Widget>[
Container(
width: _size.width,
alignment: Alignment.center,
decoration: BoxDecoration(
color: Colors.lightBlue,
borderRadius: BorderRadius.only(
topRight: Radius.circular(20.0),
topLeft: Radius.circular(20.0),
),
boxShadow: <BoxShadow>[
BoxShadow(color: Colors.grey, spreadRadius: 2.0, blurRadius: 4.0),
]
),
height: this._headerHeight,
child: Text("drag me"),
),
Expanded(
child: Container(
width: _size.width,
color: Colors.greenAccent,
alignment: Alignment.center,
child: Text("it worked!"),
),
),
],
),
)),
),
],
),
);
}
}

Following User’s Drag

onVerticalDragUpdate: (DragUpdateDetails data) {
double _draggedAmount = _size.height - data.globalPosition.dy;
this.setState(() {
this._bodyHeight = _draggedAmount;
});
},

Automatic Drag

onVerticalDragUpdate: (DragUpdateDetails data) {
double _draggedAmount = _size.height - data.globalPosition.dy;
if (this._isDragUp){
if (_draggedAmount < 100.0) this._bodyHeight = _draggedAmount;
if (_draggedAmount > 100.0) this._bodyHeight = this._maxHeight;
} else {
/// the _draggedAmount cannot be higher than maxHeight b/c maxHeight is _dragged Amount + header Height
double _downDragged = this._maxHeight - _draggedAmount;
if (_downDragged < 100.0) this._bodyHeight = _draggedAmount;
if (_downDragged > 100.0) this._bodyHeight = 0.0;
}
this.setState(() {});
},
onVerticalDragEnd: (DragEndDetails data){
if (_isDragUp) {
this._isDragUp = false;
} else {
this._isDragUp = true;
}
this.setState(() {});
},

--

--

Flutter & Node.js Full-Stack Developer

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store