strong text When I pressed on setting in drawer and then open a new drawer. How to implement a drawer when I click on button in a drawer.
image1 | image2 |
---|---|
![]() |
![]() |
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(),
drawer: MyDrawer(),
body: Center(
child: Center(child: Text('Text')),
),
),
);
}
}
class MyDrawer extends StatefulWidget {
@override
_DrawerState createState() => _DrawerState();
}
class _DrawerState extends State<MyDrawer> {
int myIndex;
PageController _controller;
@override
void initState() {
super.initState();
_controller = PageController(initialPage: 0);
}
//The Logic where you change the pages
_onChangePage(int index){
if(index != 0) setState(() => myIndex = index); //change myIndex if you're Selecting between Settings and Explore
_controller.animateToPage(index.clamp(0, 1),
duration: const Duration(milliseconds: 500), curve: Curves.linear);
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Drawer(
child: PageView.builder(
controller: _controller,
physics: NeverScrollableScrollPhysics(), //so the user can not move between pages
itemCount: 2,
itemBuilder: (context, index) {
// Original Drawer
if (index == 0) return MyWidget(
explore: () => _onChangePage(1),
settings: () => _onChangePage(2),
);
//Second Drawer form the PageView
switch(myIndex){
case 1:
return MyExploreAll(goBack: () => _onChangePage(0));
case 2:
default:
return MySettings(goBack: () => _onChangePage(0));
}
},
)
);
}
}
//The Menu Drawer (Your first image)
class MyWidget extends StatelessWidget {
final VoidCallback explore;
final VoidCallback settings;
MyWidget({this.explore, this.settings});
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildListDelegate([
ListTile(
title: Text('Send Money'),
onTap: () => print('Send Money'),
),
ListTile(
title: Text('Explore All Amazon Pay'),
onTap: () => print('Explore All Amazon Pay'),
),
const Divider(color: Colors.grey, thickness: 1,),
ListTile(
title: Text('Try Prime'),
onTap: () => print('Try Prime'),
),
ListTile(
title: Text('Explore All Programs'),
trailing: const Icon(Icons.arrow_forward_ios),
onTap: explore,
),
const Divider(color: Colors.grey, thickness: 1,),
ListTile(
title: Text('Fun Zone'),
onTap: () => print('Fun Zone'),
),
const Divider(color: Colors.grey, thickness: 1,),
//More Stuff
ListTile(
title: Text('Settings'),
trailing: const Icon(Icons.arrow_forward_ios),
onTap: settings,
),
])
)
],
);
}
}
// The settings Drawer(second image)
class MySettings extends StatelessWidget {
final VoidCallback goBack;
MySettings({this.goBack});
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildListDelegate([
ListTile(
leading: const Icon(Icons.arrow_back_ios),
title: Text('Main Menu'),
onTap: goBack,
),
ListTile(
title: Text('Settings', textScaleFactor: 3,),
onTap: () => print('Settings'),
),
const Divider(color: Colors.grey, thickness: 1,),
ListTile(
title: Text('Change Country'),
onTap: () => print('Change Country'),
),
ListTile(
title: Text('ETC'),
onTap: () => print('ETC'),
),
const Divider(color: Colors.grey, thickness: 1,),
ListTile(
title: Text('Dummy Text'),
onTap: () => print('Dummy Text'),
),
])
)
],
);
}
}
class MyExploreAll extends StatelessWidget {
final VoidCallback goBack;
MyExploreAll({this.goBack});
@override
Widget build(BuildContext context) {
return CustomScrollView(
slivers: [
SliverList(
delegate: SliverChildListDelegate([
ListTile(
leading: const Icon(Icons.arrow_back_ios),
title: Text('Main Menu'),
onTap: goBack,
),
ListTile(
title: Text('Explore All', textScaleFactor: 3,),
onTap: () => print('Explore'),
),
const Divider(color: Colors.grey, thickness: 1,),
])
)
],
);
}
}
class MyInnerDrawer extends StatelessWidget {
final String name;
final PageController _controller;
MyInnerDrawer(this._controller, this.name);
@override
Widget build(BuildContext context) {
return Column(children: [
ListTile(
title: Text(name),
trailing: const Icon(Icons.arrow_back_ios),
onTap: () => _controller.animateToPage(0,
duration: const Duration(milliseconds: 500), curve: Curves.linear),
)
]);
}
}
Using a PageView.builder() where the index 0 is the firstPage (your first image with the usual drawer) and index 1 would be the selected widget (Settings or Explore). I use an inner index myIndex to select between the multiple options in the index 1 of the PageView, thats because if I use a regular PageView and give it a list of all the options [Drawer, Explorer, Settings] if you use the controller.animateToPage() you could see the transition of all the pages, for example if you're in the page 0 and animate to page 2 you could see the page 1 for a moment (just like if you were scrolling horizontally).
If you don't want to see the animation and just jump directly to that page you can use controller.jumpToPage(index) and you wouldn't need that whole logic, it could be easier
class _DrawerState extends State<MyDrawer> {
PageController _controller;
@override
void initState() {
super.initState();
_controller = PageController(initialPage: 0);
}
_onChangePage(int index){
_controller.jumpToPage(index);
}
@override
void dispose() {
_controller?.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Drawer(
child: PageView.builder(
controller: _controller,
physics: NeverScrollableScrollPhysics(),
itemCount: 3,
itemBuilder: (context, index) {
switch(index){
case 1:
return MyExploreAll(goBack: () => _onChangePage(0));
case 2:
return MySettings(goBack: () => _onChangePage(0));
case 0:
default:
return MyWidget(
explore: () => _onChangePage(1),
settings: () => _onChangePage(2),
);
}
},
)
);
}
}
Here you just tell the PageView the childCount is 3 (the Drawer menu, Explorer and Settings) and just do a switch case to jump between those 3 indexes. You could try use animationToPage() in this example and see the effect that I beleive would be undesirable for your project