Reputation: 203
I want the drawer to always open in screen so the user do not have to slide the screen from left to right. I found many question regarding this issue but I could not find it in Dart/Flutter.
This is the solution from @aziza on how to change the content of the Scaffold. body content upon user click on the Drawer but I want it to always open.
Flutter Drawer Widget - change Scaffold.body content
Flutter Drawer Widget - change Scaffold.body content
Upvotes: 11
Views: 24351
Reputation: 4018
You need to create StateFullShellRoute
with using go_router
package
Upvotes: -1
Reputation: 31686
Instead of a Drawer
you might want to consider the OOTB NavigationRail
As per the official documentation you can create a local sample project with
flutter create --sample=material.NavigationRail.1 mysample
Customized code and Live demo which shows the rail expanded by default:
import 'package:flutter/material.dart';
void main() {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'NavigationRail',
home: const MyHomePage(title: 'NavigationRail'),
debugShowCheckedModeBanner: false,
);
}
}
class MyHomePage extends StatefulWidget {
const MyHomePage({super.key, required this.title});
final String title;
@override
State<MyHomePage> createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
int _selectedIndex = 0;
bool extended =false;
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Row(
children: <Widget>[
IntrinsicWidth(
child: NavigationRail(
elevation: 3,
extended: true,
selectedIndex: _selectedIndex,
onDestinationSelected: (int index) {
setState(() {
print(index);
_onItemTapped(index);
// _selectedIndex = index;
});
},
labelType: NavigationRailLabelType.none,
destinations: const <NavigationRailDestination>[
NavigationRailDestination(
icon: Icon(Icons.bookmark_border),
selectedIcon: Icon(Icons.book),
label: Text('Accented'),
),
NavigationRailDestination(
icon: Icon(Icons.star_border),
selectedIcon: Icon(Icons.star),
label: Text('Starred'),
),
],
),
),
const VerticalDivider(thickness: 0, width: 0),
Expanded(
child: Center(
child: Text("selected: $_selectedIndex" ),
),
)
],
),
);
}
}
Moreover, the NavigationRail
can be used as a Drawer
's child, so you could for example use something like adaptive_breakpoints
to detect the user's screen size and display a regular drawer in mobile viewports and the wide split view with the same navigationRail instance on desktop viewports.
Upvotes: 2
Reputation: 21
I have done this using scaffold drawer. Please see and try this
class _Dashbord extends State<Dashbord> {
Widget bodyWidget = DashboardInitialContent();
@override
Widget build(BuildContext context) {
final bool displayMobileLayout = MediaQuery.of(context).size.width < 500;
return Row(
children: [
if (!displayMobileLayout)
Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
// padding: EdgeInsets.zero,
children: [
DrawerHeader(
// decoration: const BoxDecoration(
// color: Colors.white,
// ),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
child: Image.asset(
"assets/images/3c98d8a48cfed2f87f377ec2b30130b4b9195af4.png"),
),
],
),
),
ListTile(
hoverColor: Colors.grey,
leading: const Icon(
Icons.dashboard,
color: Colors.deepOrange,
),
title: const Text(
'Dashboard',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w600,
color: Colors.deepOrange,
),
),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
setState(() {
bodyWidget = DashboardInitialContent();
});
},
)
],
),
),
Expanded(
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: displayMobileLayout ? true : false,
backgroundColor: Colors.deepOrange,
actions: [
IconButton(
icon: const Icon(Icons.notification_important_rounded),
tooltip: 'Notification',
onPressed: () {
ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('This is a snackbar')));
},
),
PopupMenuButton(
icon: const Icon(Icons.person_rounded),
tooltip: 'Profile',
itemBuilder: (BuildContext context) => <PopupMenuEntry>[
PopupMenuItem(
child: ListTile(
leading: Icon(Icons.edit),
title: Text('Edit Profile'),
onTap: () {
setState(() {
bodyWidget = UserProfile();
Navigator.pop(context);
});
},
),
),
PopupMenuItem(
child: ListTile(
leading: Icon(Icons.lock),
title: Text('Change Password'),
onTap: () {
setState(() {
bodyWidget = ChangePassword();
Navigator.pop(context);
});
},
),
),
const PopupMenuItem(
child: ListTile(
leading: Icon(Icons.logout),
title: Text('Sign out'),
),
),
],
),
],
),
drawer: displayMobileLayout
? Drawer(
// Add a ListView to the drawer. This ensures the user can scroll
// through the options in the drawer if there isn't enough vertical
// space to fit everything.
child: ListView(
// Important: Remove any padding from the ListView.
// padding: EdgeInsets.zero,
children: [
DrawerHeader(
// decoration: const BoxDecoration(
// color: Colors.white,
// ),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.start,
children: [
SizedBox(
child: Image.asset(
"assets/images/3c98d8a48cfed2f87f377ec2b30130b4b9195af4.png"),
),
],
),
),
ListTile(
hoverColor: Colors.grey,
leading: const Icon(
Icons.dashboard,
color: Colors.deepOrange,
),
title: const Text(
'Dashboard',
style: TextStyle(
fontSize: 20.0,
fontWeight: FontWeight.w600,
color: Colors.deepOrange,
),
),
onTap: () {
// Update the state of the app
// ...
// Then close the drawer
setState(() {
bodyWidget = DashboardInitialContent();
});
Navigator.pop(context);
},
)
],
),
)
: null,
body: bodyWidget,
),
)
],
);
}
}
Upvotes: 1
Reputation: 458
I think my package suits your needs. I designed this originally for a desktop flutter app but decided to.make a package out of it.
https://pub.dev/packages/side_navigation
In the README you can also find an example and some pictures to showcase.
Cheers!
Upvotes: 3
Reputation: 3147
You may try this :
import 'package:flutter/material.dart';
class SideMenuScreen extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Screen'),
),
body: Column(
children: <Widget>[
Expanded(
child: Row(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Flexible(
child: ListView(
children: <Widget>[
ListTile(title: Text("Menu A")),
ListTile(title: Text("Menu B")),
ListTile(title: Text("Menu C")),
ListTile(title: Text("Menu D")),
ListTile(title: Text("Menu E")),
ListTile(title: Text("Menu F")),
ListTile(title: Text("Menu G")),
ListTile(title: Text("Menu H")),
ListTile(title: Text("Menu I")),
ListTile(title: Text("Menu J")),
ListTile(title: Text("Menu K")),
ListTile(title: Text("Menu L")),
ListTile(title: Text("Menu M")),
],
),
),
Expanded(
child: Container(
child: Center(child: Text('Content')),
color: Colors.black26,
),
),
],
),
),
],
),
);
}
}
We can improve to more be interactive by PageView : Github Repo
Flexible(
child: StaticDrawer(),
),
Expanded(
child: PageView(
children: <Widget>[
MainContent(),
MainContent(),
MainContent(),
],
),
),
later you will find this ..
Upvotes: 13