I want to create a drop down menu like the image below, Which is opened by touching and dragging and closing by touching the outside.
before dragging
after dragging
Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false
),
body: Stack(
children: <Widget>[
Container(
height: 200,
decoration: BoxDecoration(
color: Colors.white,
borderRadius: BorderRadius.vertical(bottom: Radius.circular(20))
),
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
Align(
alignment: Alignment.bottomCenter,
child: Column(
children: <Widget>[
Padding(
padding: EdgeInsets.symmetric(horizontal: 40),
child: Divider(
color: Colors.blueGrey[500],
height: 10,
indent: 5,
),
),
Icon(FontAwesomeIcons.angleDoubleDown,size: 15,color: Colors.blueGrey[500],)
],
),
)
],
),
),
Center(child: Text('List View'),)
],
)
)
I want to change the height, but I encounter overflow error! What is the best way to make this widget? Can I do this within the AppBar?
You can do this in some ways, but one that came up in mind immediately was to use a CustomPaint
widget with your own CustomPainter
at the top of a Stack
so you can actually keep your other widgets below the scrolled bar.
I've tried to replicate what you've shown on the images but feel free to tweak it to your needs.
const kMinScrollBarHeight = 20.0;
class MyScreen extends StatefulWidget {
_MyScreenState createState() => _MyScreenState();
}
class _MyScreenState extends State<MyScreen> {
double _scrollBarOffset = 0.0;
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: const Color.fromRGBO(13, 23, 35, 1.0),
appBar: AppBar(
backgroundColor: const Color.fromRGBO(255, 72, 18, 1.0),
),
body: Stack(children: <Widget>[
GestureDetector(
onVerticalDragUpdate: (tapDetails) => setState(() => _scrollBarOffset = tapDetails.globalPosition.dy),
child: Stack(
children: <Widget>[
Center(
child: Text(
'My screen widgets',
style: TextStyle(color: Colors.white),
),
),
Stack(
children: <Widget>[
Positioned(
bottom: MediaQuery.of(context).size.height -
max(_scrollBarOffset,
MediaQuery.of(context).padding.top + kToolbarHeight + kMinScrollBarHeight),
child: CustomPaint(
painter: MyDraggable(),
child: Container(
height: MediaQuery.of(context).size.height,
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
FlutterLogo(
size: 100.0,
),
Text('Flutter is awesome'),
],
),
),
),
),
],
),
],
),
),
]),
);
}
}
class MyDraggable extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
final Paint paint = Paint()..color = Colors.white;
final Radius cornerRadius = Radius.circular(20.0);
final double lineMargin = 30.0;
// Draw slider
canvas.drawRRect(
RRect.fromLTRBAndCorners(0.0, 0.0, size.width, size.height,
bottomLeft: cornerRadius, bottomRight: cornerRadius),
paint);
paint.color = Colors.black.withAlpha(64);
paint.strokeWidth = 1.5;
// Draw triangle
canvas.drawPoints(
PointMode.polygon,
[
Offset((size.width / 2) - 5.0, size.height - 10.0),
Offset((size.width / 2) + 5.0, size.height - 10.0),
Offset((size.width / 2), size.height - 5.0),
Offset((size.width / 2) - 5.0, size.height - 10.0),
],
paint);
// Draw line
canvas.drawLine(Offset(lineMargin, size.height - kMinScrollBarHeight),
Offset(size.width - lineMargin, size.height - kMinScrollBarHeight), paint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With