Created
December 22, 2019 17:32
-
-
Save osaxma/dc735020351d72862713fd69e7ba1b96 to your computer and use it in GitHub Desktop.
Flutter Backdrop Example for DartPad
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
// taken from: https://github.com/iampawan/FlutterBackdrop | |
// copy paste to https://dartpad.dev/ and should work | |
import 'package:flutter/material.dart'; | |
void main() { | |
runApp(MaterialApp( | |
debugShowCheckedModeBanner: false, | |
theme: ThemeData(primarySwatch: Colors.teal), | |
home: BackdropPage(), | |
)); | |
} | |
class BackdropPage extends StatefulWidget { | |
@override | |
_BackdropPageState createState() => _BackdropPageState(); | |
} | |
class _BackdropPageState extends State<BackdropPage> | |
with SingleTickerProviderStateMixin { | |
AnimationController controller; | |
@override | |
void initState() { | |
super.initState(); | |
controller = AnimationController( | |
vsync: this, duration: Duration(milliseconds: 100), value: 1.0); | |
} | |
@override | |
void dispose() { | |
super.dispose(); | |
controller.dispose(); | |
} | |
bool get isPanelVisible { | |
final AnimationStatus status = controller.status; | |
return status == AnimationStatus.completed || | |
status == AnimationStatus.forward; | |
} | |
@override | |
Widget build(BuildContext context) { | |
return new Scaffold( | |
appBar: new AppBar( | |
title: new Text("Backdrop"), | |
elevation: 0.0, | |
actions: [IconButton( | |
onPressed: () { | |
controller.fling(velocity: isPanelVisible ? -1.0 : 1.0); | |
}, | |
icon: new AnimatedIcon( | |
icon: AnimatedIcons.ellipsis_search, | |
progress: controller.view, | |
), | |
)], | |
), | |
body: new TwoPanels( | |
controller: controller, | |
), | |
); | |
} | |
} | |
// ============================================= | |
class TwoPanels extends StatefulWidget { | |
final AnimationController controller; | |
TwoPanels({this.controller}); | |
@override | |
_TwoPanelsState createState() => _TwoPanelsState(); | |
} | |
class _TwoPanelsState extends State<TwoPanels> { | |
static const header_height = 32.0; | |
Animation<RelativeRect> getPanelAnimation(BoxConstraints constraints) { | |
final height = constraints.biggest.height; | |
final backPanelHeight = height - header_height; | |
final frontPanelHeight = -header_height; | |
return RelativeRectTween( | |
begin: RelativeRect.fromLTRB( | |
0.0, backPanelHeight, 0.0, frontPanelHeight), | |
end: RelativeRect.fromLTRB(0.0, 0.0, 0.0, 0.0)) | |
.animate(new CurvedAnimation( | |
parent: widget.controller, curve: Curves.linear)); | |
} | |
Widget bothPanels(BuildContext context, BoxConstraints constraints) { | |
final ThemeData theme = Theme.of(context); | |
return Container( | |
child: Stack( | |
children: <Widget>[ | |
Container( | |
color: theme.primaryColor, | |
child: Center( | |
child: Text( | |
"Back Panel", | |
style: TextStyle(fontSize: 24.0, color: Colors.white), | |
), | |
), | |
), | |
PositionedTransition( | |
rect: getPanelAnimation(constraints), | |
child: Material( | |
elevation: 12.0, | |
borderRadius: BorderRadius.only( | |
topLeft: Radius.circular(16.0), | |
topRight: Radius.circular(16.0)), | |
child: Column( | |
children: <Widget>[ | |
Container( | |
height: header_height, | |
child: Center( | |
child: Text( | |
"Shop Here", | |
style: Theme.of(context).textTheme.button, | |
), | |
), | |
), | |
Expanded( | |
child: Center( | |
child: Text("Front Panel", | |
style: | |
TextStyle(fontSize: 24.0, color: Colors.black)), | |
), | |
) | |
], | |
), | |
), | |
) | |
], | |
), | |
); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return LayoutBuilder( | |
builder: bothPanels, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment