Last active
January 17, 2020 13:11
-
-
Save gladimdim/31c5f5035d02ece1c18433a4caf3444d to your computer and use it in GitHub Desktop.
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 'package:flutter/material.dart'; | |
import 'dart:ui' as ui; | |
final Color darkBlue = Color.fromARGB(255, 18, 32, 47); | |
const double APP_BAR_HEIGHT = 40.0; | |
void main() { | |
runApp(MyApp()); | |
} | |
class MyApp extends StatefulWidget { | |
@override | |
_MyAppState createState() => _MyAppState(); | |
} | |
class _MyAppState extends State<MyApp> { | |
String message = 'Press the Menu Button to expand the menu!\n Press anywhere to hide the menu!'; | |
@override | |
Widget build(BuildContext context) { | |
return MaterialApp( | |
theme: whiteTheme, | |
debugShowCheckedModeBanner: false, | |
home: NarrowScaffold( | |
body: Center( | |
child: Text(message, | |
style: TextStyle( | |
color: Colors.black, | |
fontSize: 30, | |
fontWeight: FontWeight.bold)), | |
), | |
title: 'My Custom App Bar Title', | |
// titleView: | |
// Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ | |
// Text('First'), | |
// Text('Second'), | |
// ]), | |
actions: [ | |
AppBarObject( | |
text: "The First Menu Item", | |
onTap: () => { | |
setState(() { | |
message = 'The First Menu'; | |
}) | |
}, | |
), | |
AppBarObject( | |
text: "The Second Menu Item", | |
onTap: () => { | |
setState(() { | |
message = 'The Second Menu'; | |
}) | |
}, | |
), | |
AppBarObject( | |
text: "The Third Menu Item", | |
onTap: () => { | |
setState(() { | |
message = 'The Third Menu'; | |
}) | |
}, | |
), | |
AppBarObject( | |
text: "The Fourth Menu Item", | |
onTap: () => { | |
setState(() { | |
message = 'The Fourth Menu'; | |
}) | |
}, | |
), | |
]), | |
); | |
} | |
} | |
class NarrowScaffold extends StatefulWidget { | |
final Widget body; | |
final List<AppBarObject> actions; | |
final String title; | |
final Widget titleView; | |
NarrowScaffold({ | |
this.body, | |
this.actions, | |
this.title, | |
this.titleView, | |
}); | |
@override | |
_NarrowScaffoldState createState() => _NarrowScaffoldState(); | |
} | |
class _NarrowScaffoldState extends State<NarrowScaffold> { | |
bool expanded = false; | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
backgroundColor: Theme.of(context).backgroundColor, | |
body: SafeArea( | |
child: Stack( | |
children: [ | |
Padding( | |
padding: EdgeInsets.only(top: APP_BAR_HEIGHT + 8), | |
child: BorderedContainer( | |
child: widget.body, | |
)), | |
if (expanded) | |
SizedBox( | |
height: MediaQuery.of(context).size.height, | |
child: new BackdropFilter( | |
filter: new ui.ImageFilter.blur(sigmaX: 1.5, sigmaY: 1.5), | |
child: new Container( | |
decoration: new BoxDecoration( | |
color: Colors.black.withOpacity(0.2), | |
), | |
child: Container(child: GestureDetector(onTap: () { | |
setState(() { | |
expanded = false; | |
}); | |
})), | |
), | |
), | |
), | |
AppBarCustom( | |
title: widget.title, | |
titleView: widget.titleView, | |
appBarButtons: widget.actions, | |
expanded: expanded, | |
onExpanded: (expand) { | |
setState(() { | |
expanded = expand; | |
}); | |
}, | |
), | |
], | |
), | |
), | |
); | |
} | |
} | |
class AppBarCustom extends StatefulWidget { | |
final String title; | |
final Widget titleView; | |
final List<AppBarObject> appBarButtons; | |
final Function(bool expand) onExpanded; | |
final bool expanded; | |
AppBarCustom({ | |
this.appBarButtons = const [], | |
@required this.title, | |
this.onExpanded, | |
this.titleView, | |
this.expanded = false, | |
}); | |
@override | |
_AppBarCustomState createState() => _AppBarCustomState(); | |
} | |
class _AppBarCustomState extends State<AppBarCustom> { | |
@override | |
Widget build(BuildContext context) { | |
var menuIcon = | |
widget.expanded ? Icons.arrow_drop_up : Icons.arrow_drop_down; | |
return Positioned( | |
top: 0, | |
left: 0.0, | |
right: 0, | |
child: BorderedContainer( | |
child: Container( | |
padding: EdgeInsets.only(top: 8.0), | |
color: Theme.of(context).backgroundColor, | |
height: widget.expanded | |
? (widget.appBarButtons.length * 50).toDouble() + APP_BAR_HEIGHT | |
: APP_BAR_HEIGHT, | |
child: Column( | |
crossAxisAlignment: CrossAxisAlignment.end, | |
children: <Widget>[ | |
Row( | |
crossAxisAlignment: CrossAxisAlignment.start, | |
mainAxisAlignment: MainAxisAlignment.spaceBetween, | |
children: <Widget>[ | |
Padding( | |
padding: EdgeInsets.only(left: 10), | |
child: widget.titleView != null | |
? SizedBox( | |
width: MediaQuery.of(context).size.width * 0.7, | |
child: widget.titleView, | |
) | |
: Text( | |
widget.title, | |
style: Theme.of(context).textTheme.title, | |
textAlign: TextAlign.center, | |
), | |
), | |
if (widget.appBarButtons != null) | |
ButtonTextIcon( | |
text: 'Menu', | |
onTap: _toggleExpandedMenu, | |
icon: Icon( | |
menuIcon, | |
), | |
), | |
], | |
), | |
if (widget.expanded) | |
SizedBox( | |
height: (widget.appBarButtons.length * 50).toDouble(), | |
width: MediaQuery.of(context).size.width, | |
child: ListView( | |
scrollDirection: Axis.vertical, | |
children: widget.appBarButtons | |
.map((obj) => _appBarObjectToButton(obj, context)) | |
.toList(), | |
), | |
), | |
], | |
), | |
), | |
), | |
); | |
} | |
Widget _appBarObjectToButton(AppBarObject object, BuildContext context) { | |
return AppBarButton( | |
onTap: _callbackerHandler(object.onTap), | |
text: object.text, | |
color: Theme.of(context).primaryColor, | |
); | |
} | |
_toggleExpandedMenu() { | |
widget.onExpanded(!widget.expanded); | |
} | |
_callbackerHandler(VoidCallback callback) { | |
return () { | |
_toggleExpandedMenu(); | |
callback(); | |
}; | |
} | |
} | |
class AppBarObject { | |
final VoidCallback onTap; | |
final String text; | |
AppBarObject({@required this.text, @required this.onTap}); | |
} | |
class AppBarButton extends StatelessWidget { | |
final VoidCallback onTap; | |
final Color color; | |
final String text; | |
AppBarButton({this.onTap, this.color, this.text}); | |
@override | |
Widget build(BuildContext context) { | |
return FlatButton( | |
splashColor: color, | |
onPressed: onTap, | |
child: Padding( | |
padding: const EdgeInsets.all(8.0), | |
child: Center( | |
child: Text( | |
text, | |
style: TextStyle( | |
fontWeight: FontWeight.bold, | |
color: color, | |
), | |
), | |
), | |
), | |
); | |
} | |
} | |
class BorderedContainer extends StatelessWidget { | |
final Widget child; | |
BorderedContainer({this.child}); | |
@override | |
Widget build(BuildContext context) { | |
return Container( | |
decoration: BoxDecoration( | |
color: Theme.of(context).backgroundColor, | |
border: Border.all( | |
color: Theme.of(context).primaryColor, | |
width: 3.0, | |
), | |
), | |
child: child); | |
} | |
} | |
class ButtonTextIcon extends StatelessWidget { | |
final String text; | |
final Icon icon; | |
final Color color; | |
final VoidCallback onTap; | |
ButtonTextIcon({this.text, this.icon, this.color, this.onTap}); | |
@override | |
Widget build(BuildContext context) { | |
return InkWell( | |
splashColor: color, | |
child: Row( | |
children: <Widget>[ | |
Text( | |
text, | |
style: TextStyle(color: color), | |
), | |
icon | |
], | |
), | |
onTap: onTap, | |
); | |
} | |
} | |
var blackTheme = ThemeData( | |
primaryColor: Colors.white, | |
backgroundColor: Colors.black, | |
accentColor: Colors.white, | |
fontFamily: 'Roboto', | |
unselectedWidgetColor: Colors.white, | |
textTheme: TextTheme( | |
body1: TextStyle( | |
fontFamily: "Raleway-Bold", | |
fontSize: 18, | |
color: Colors.white, | |
), | |
title: TextStyle( | |
fontSize: 20, | |
fontWeight: FontWeight.bold, | |
color: Colors.white, | |
fontFamily: 'Roboto', | |
), | |
button: TextStyle( | |
fontFamily: 'Montserrat', | |
fontSize: 20.0, | |
fontWeight: FontWeight.bold, | |
color: Colors.white, | |
), | |
), | |
hintColor: Colors.white, | |
focusColor: Colors.yellow, | |
iconTheme: IconThemeData( | |
color: Colors.white, | |
), | |
appBarTheme: AppBarTheme( | |
color: Colors.black, | |
iconTheme: IconThemeData( | |
color: Colors.white, | |
), | |
), | |
canvasColor: Colors.black, | |
); | |
var whiteTheme = ThemeData( | |
primaryColor: Colors.black, | |
backgroundColor: Colors.white, | |
accentColor: Colors.black, | |
fontFamily: 'Roboto', | |
unselectedWidgetColor: Colors.black, | |
textTheme: TextTheme( | |
body1: TextStyle( | |
fontFamily: "Raleway-Bold", | |
fontSize: 18, | |
color: Colors.black, | |
), | |
title: TextStyle( | |
color: Colors.black, | |
fontSize: 20.0, | |
fontWeight: FontWeight.bold, | |
fontFamily: 'Roboto', | |
), | |
button: TextStyle( | |
fontFamily: 'Montserrat', | |
fontSize: 20.0, | |
fontWeight: FontWeight.bold, | |
color: Colors.black, | |
), | |
), | |
iconTheme: IconThemeData( | |
color: Colors.black, | |
), | |
appBarTheme: AppBarTheme( | |
color: Colors.white, | |
iconTheme: IconThemeData( | |
color: Colors.black, | |
), | |
), | |
canvasColor: Colors.white, | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment