Created
April 16, 2020 08:01
-
-
Save edbond/7fbad05870cf68ae0354e6df33f53bfd to your computer and use it in GitHub Desktop.
Flutter Drawer
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:google_fonts/google_fonts.dart'; | |
class TransitionDrawer extends StatefulWidget { | |
final Widget child; | |
final StreamController<void> toggleStream; | |
TransitionDrawer({ | |
@required this.child, | |
@required this.toggleStream, | |
}); | |
@override | |
_TransitionDrawerState createState() => _TransitionDrawerState(); | |
} | |
enum DrawerState { Opened, Closed } | |
enum OnRelease { toLeft, toRight } | |
class _TransitionDrawerState extends State<TransitionDrawer> | |
with TickerProviderStateMixin { | |
AnimationController controller; | |
Animation<double> animation; | |
OnRelease onRelease = OnRelease.toLeft; | |
bool trackHorizontalDrag = false; | |
DrawerState _drawerState = DrawerState.Closed; | |
double dragOffset; | |
@override | |
void initState() { | |
super.initState(); | |
controller = AnimationController( | |
lowerBound: 0, | |
upperBound: 1, | |
duration: const Duration(milliseconds: 200), | |
vsync: this, | |
); | |
animation = Tween<double>(begin: 0, end: 100).animate(controller) | |
..addStatusListener((status) { | |
// print("status ${status}"); | |
if (status == AnimationStatus.completed) { | |
_drawerState = DrawerState.Opened; | |
onRelease = OnRelease.toRight; | |
} | |
if (status == AnimationStatus.dismissed) { | |
_drawerState = DrawerState.Closed; | |
onRelease = OnRelease.toLeft; | |
} | |
}); | |
widget.toggleStream.stream.listen((event) { | |
// print("animating? ${controller.isAnimating}, drawer state=$_drawerState"); | |
if (controller.isAnimating) { | |
return; | |
} | |
if (_drawerState == DrawerState.Closed) { | |
controller.forward(); | |
} else { | |
controller.reverse(); | |
} | |
}); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
controller.dispose(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
var width = MediaQuery.of(context).size.width; | |
return Stack( | |
children: [ | |
Container( | |
color: Colors.blue, | |
child: ListView( | |
children: <Widget>[ | |
Container( | |
decoration: BoxDecoration( | |
color: Colors.white, | |
), | |
child: Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: Text( | |
"Login", | |
style: GoogleFonts.robotoMono(), | |
), | |
), | |
), | |
], | |
), | |
), | |
GestureDetector( | |
onHorizontalDragStart: (details) { | |
var progress = animation.value; | |
var leftX = (width * 0.85) * (progress / 100.0); | |
var x = details.globalPosition.dx; | |
dragOffset = x - leftX; | |
// print( | |
// "start drag! $x, width=$width, progress=$progress, (width*0.8)*progress=$leftX, $dragDelta"); | |
if (_drawerState == DrawerState.Opened) { | |
trackHorizontalDrag = true; | |
return; | |
} | |
if (details.globalPosition.dx < width * 0.15) { | |
trackHorizontalDrag = true; | |
} else { | |
trackHorizontalDrag = false; | |
} | |
}, | |
onHorizontalDragUpdate: (details) { | |
if (!trackHorizontalDrag) return; | |
var x = details.globalPosition.dx; | |
controller.value = (x - dragOffset) / (width * 0.85); | |
if (x < width / 2) { | |
onRelease = OnRelease.toLeft; | |
} else { | |
onRelease = OnRelease.toRight; | |
} | |
}, | |
onHorizontalDragEnd: (details) { | |
if (onRelease == OnRelease.toLeft) { | |
controller.reverse(); | |
} else { | |
controller.forward(); | |
} | |
trackHorizontalDrag = false; | |
}, | |
child: AnimatedBuilder( | |
animation: animation, | |
child: widget.child, | |
builder: (context, child) { | |
var scale = (0.85 - 1) / 100 * animation.value + 1; | |
var translateX = (animation.value / 100 * width * 0.85); | |
return Transform( | |
alignment: Alignment.centerLeft, | |
transform: Matrix4.identity() | |
..translate(translateX, 0) | |
..scale(scale), | |
child: child, | |
); | |
}, | |
), | |
), | |
Positioned( | |
left: (width * 0.15), | |
top: 0, | |
width: 1, | |
bottom: 0, | |
child: Container( | |
color: Colors.redAccent, | |
), | |
) | |
], | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment