Rosanna Trevisan
Rosanna Trevisan

Reputation: 452

Flutter avoid re-opening drawer page

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

Answers (3)

Ali Murat
Ali Murat

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

Javier Hinmel
Javier Hinmel

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

CopsOnRoad
CopsOnRoad

Reputation: 268404

enter image description here


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

Related Questions