I'm new to flutter but I have a curiosity. Considering the typical bootstrap admin UI that you can find online and the typical left menu, how would you recreate that with flutter? I'm particularly interested on a left menu that can be resized clicking on a button and on a sub-menu that can appear and disappear.
An example can be found here
Edit:
I want to be be clear about the effect I'm trying to reproduce as well. If you click the link relative to the example on the left you see a number of menu. For instance, clicking on Base
you are going to see a vertical menu appearing and disappearing. I would like to know how to reproduce it as well.
Thanks
Thanks
I have tried to re-create the same design with some minor changes in Flutter. I have to enable flutter web support by following the instructions here: Flutter Web
Regarding the left menu, I have used AnimatedSize
widget to give the sliding drawer feel & placed it inside Row
.
Please find the code below:
import 'package:flutter/material.dart';
final Color darkBlue = Color.fromARGB(255, 18, 32, 47);
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData.dark().copyWith(scaffoldBackgroundColor: darkBlue),
debugShowCheckedModeBanner: false,
home: Scaffold(
body: Center(
child: MyWidget(),
),
),
);
}
}
class MyWidget extends StatefulWidget {
@override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin {
final colors = <Color>[Colors.indigo, Colors.blue, Colors.orange, Colors.red];
double _size = 250.0;
bool _large = true;
void _updateSize() {
setState(() {
_size = _large ? 250.0 : 0.0;
_large = !_large;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Row(
children: [
AnimatedSize(
curve: Curves.easeIn,
vsync: this,
duration: Duration(seconds: 1),
child: LeftDrawer(size: _size)),
Expanded(
flex: 4,
child: Container(
child: Column(
children: [
Container(
color: Colors.white,
padding: const EdgeInsets.all(8),
child: Row(
children: [
IconButton(
icon: Icon(Icons.menu, color: Colors.black87),
onPressed: () {
_updateSize();
},
),
FlatButton(
child: Text(
'Dashboard',
style: const TextStyle(color: Colors.black87),
),
onPressed: () {},
),
FlatButton(
child: Text(
'User',
style: const TextStyle(color: Colors.black87),
),
onPressed: () {},
),
FlatButton(
child: Text(
'Settings',
style: const TextStyle(color: Colors.black87),
),
onPressed: () {},
),
const Spacer(),
IconButton(
icon: Icon(Icons.brightness_3, color: Colors.black87),
onPressed: () {},
),
IconButton(
icon: Icon(Icons.notification_important,
color: Colors.black87),
onPressed: () {},
),
CircleAvatar(),
],
),
),
Container(
height: 1,
color: Colors.black12,
),
Card(
margin: EdgeInsets.zero,
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(0),
),
child: Container(
color: Colors.white,
padding: const EdgeInsets.all(20),
child: Row(
children: [
Text(
'Home / Admin / Dashboard',
style: const TextStyle(color: Colors.black),
),
],
),
),
),
Expanded(
child: ListView(
children: [
Row(
children: [
_container(0),
_container(1),
_container(2),
_container(3),
],
),
Container(
height: 400,
color: Color(0xFFE7E7E7),
padding: const EdgeInsets.all(16),
child: Card(
color: Colors.white,
child: Container(
padding: const EdgeInsets.all(16),
child: Text(
'Traffic',
style: const TextStyle(color: Colors.black87),
),
),
),
),
],
),
),
],
),
),
),
],
),
);
}
Widget _container(int index) {
return Expanded(
child: Container(
padding: const EdgeInsets.all(20),
color: Color(0xFFE7E7E7),
child: Card(
color: Color(0xFFE7E7E7),
child: Container(
color: colors[index],
width: 250,
height: 140,
padding: const EdgeInsets.all(20),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
Expanded(
child: Text(
'9.823',
style: TextStyle(fontSize: 24),
)),
Icon(Icons.more_vert),
],
),
Text('Members online')
],
),
),
),
),
);
}
}
class LeftDrawer extends StatelessWidget {
const LeftDrawer({
Key key,
this.size,
}) : super(key: key);
final double size;
@override
Widget build(BuildContext context) {
return Expanded(
flex: 1,
child: Container(
width: size,
color: const Color(0xFF2C3C56),
child: ListView(
children: [
Container(
alignment: Alignment.center,
padding: const EdgeInsets.all(16),
color: Color(0xFF223047),
child: Text('CORE UI'),
),
_tile('Dashboard'),
Container(
padding: const EdgeInsets.only(left: 10),
margin: const EdgeInsets.only(top: 30),
child: Text('THEME',
style: TextStyle(
color: Colors.white54,
))),
_tile('Colors'),
_tile('Typography'),
_tile('Base'),
_tile('Buttons'),
],
),
),
);
}
Widget _tile(String label) {
return ListTile(
title: Text(label),
onTap: () {},
);
}
}
Thanks, this is really really cool. What about the vertical menu? Is there a way for me to click on a voice and see the submenu appearing and disappearing?
Yes, that can be achieved as well. If you find this useful, you can upvote or accept the answer.
Absolutely, could you update your answer adding that part please? I'll upvote and accept it for sure. Great work
Can you please be more specific - like which vertical menu are you talking about? Are you referring to the Base option in Components vertical menu or the Notification vertical menu?
The question was closed because not super clear. I'll create a new one in a sec