Skip to content

Instantly share code, notes, and snippets.

@gladimdim
Last active January 17, 2020 13:11
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save gladimdim/31c5f5035d02ece1c18433a4caf3444d to your computer and use it in GitHub Desktop.
Save gladimdim/31c5f5035d02ece1c18433a4caf3444d to your computer and use it in GitHub Desktop.
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