Reputation: 452
I have a navigation Drawer
and the entries inside it look like this:
ListTile(
onTap: () => doRoute(context, '/second'),
title: Text(...),
),
And the method doRoute
is the following:
String _currentRoute = '/';
void doRoute(BuildContext context, String routename) {
if (_currentRoute != routename) {
Navigator.of(context).popAndPushNamed(routename);
_currentRoute = routename;
}
else
Navigator.of(context).pop();
}
I am doing this because I do not want to open the same page twice. Say that in the drawer I click on Settings
. If I open the drawer again and click on Settings
I do NOT want the drawer to open again settings because I am already there!
How can I do it? Why is not the string comparison working?
Upvotes: 2
Views: 2032
Reputation: 161
I solved this problem by changing the states of the variables.
Define a global variable in settingPage.dart
bool clickableSettings = true;
My homePage.dart
@override
void initState() {
print("Set clickableSettings is true");
clickableSettings = true;
super.initState();
}
When clicked on setting
onPressed: () {
if (clickableSettings == false) {
print("clickableSettings is false");
} else if (clickableSettings == true) {
clickableSettings = false;
Navigator.of(context).pushNamedAndRemoveUntil(
'/setting', (Route<dynamic> route) => false);
}
},
Upvotes: 0
Reputation: 719
I solved, without instance variable: Define your routes:
providers: providers,
child: MaterialApp(
title: Strings.appName,
routes: <String, WidgetBuilder>{
Strings.login: (BuildContext context) => LoginPage(),
Strings.inicio: (BuildContext context) => HomePage(),
}
...
then, in your listItem drawer onTap function, you can get the name of the current route:
class _ListItemDrawer extends StatelessWidget {
final String icon;
final String title;
_ListItemDrawer({this.icon, this.title});
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.fromLTRB(0, 40, 0, 0),
child: ListTile(
leading: Image.asset(
icon,
color: Colors.black,
height: ScreenUtil().setHeight(100),
),
title: Text(
title,
style: Styles.drawerTextStyle(context),
),
onTap: () {
Navigator.pop(context);
final isCurrentPage = ModalRoute.of(context).settings.name == title;
if(!isCurrentPage){
Navigator.pushNamed(context, title);
}
},
),
);
}
}
You have to use the same string in your routes as in your title of the listItem. i.e:
...
child: Drawer(
child: Container(
color: drawerGreyColor,
child: ListView(
padding: EdgeInsets.zero,
children: <Widget>[
_ListItemDrawer(
icon: 'assets/images/home-icon.png',
title: Strings.inicio),
...
I Hope it helps.
Upvotes: 0
Reputation: 268404
Here is how I did it (Full code)
void main() {
runApp(
MaterialApp(
routes: {
"/": (context) => HomePage(),
"/settings": (context) => SettingsPage(),
},
),
);
}
String _currentRoute = "/";
Widget buildDrawer(context) {
return Drawer(
child: SafeArea(
child: Column(
children: <Widget>[
ListTile(
title: Text("Home"),
onTap: () => doRoute(context, '/'),
),
ListTile(
title: Text("Settings"),
onTap: () => doRoute(context, '/settings'),
),
],
),
),
);
}
void doRoute(BuildContext context, String name) {
if (_currentRoute != name)
Navigator.pushReplacementNamed(context, name);
else
Navigator.pop(context);
_currentRoute = name;
}
// Page 1 (HomePage)
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Home")),
body: Container(color: Colors.blue.withOpacity(0.5)),
drawer: buildDrawer(context),
);
}
}
// Page 2 (SettingsPage)
class SettingsPage extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text("Settings")),
body: Container(color: Colors.orange.withOpacity(0.5)),
drawer: buildDrawer(context),
);
}
}
Upvotes: 3