Search code examples
flutterdartroutesnavigationnavigator

How to use Navigator 2.0 to navigate to any page?


I'm trying to navigate to multiple pages from a single page, when user taps on the elevated button it should take the user to the desired page. I can't figure out how to navigate. Here is my main.dart file. And what is the use of ValueKey?


void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  State<MyApp> createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  final TextEditingController _emailController = TextEditingController();
  final TextEditingController _passwordController = TextEditingController();

  void _handleEmail(String email) {
    setState(() {
      _emailController.text = email;
    });
    print(email);
  }

  void _handlePassword(String password) {
    setState(() {
      _passwordController.text = password;
    });
    print(password);
  }

  bool _logIn = true;
  int selectedPage = 0;
  @override
  Widget build(BuildContext context) {
    final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    return MaterialApp(
      home: Navigator(
        key: navigatorKey,
        pages: [
          if (selectedPage == 0)
            MaterialPage(
              key: const ValueKey("login"),
              child: Login(
                isLogin: (value) {
                  setState(() {
                  //  _logIn = !_logIn;
                    _logIn = value;
                //    print(_logIn);
                  });
                },
                onTapOne: _handleEmail,
                onTapTwo: _handlePassword,
              ),
            ),
          if (_logIn)
            MaterialPage(
                key: Home.valueKey,
                child: Home(
                  selectedPage: (value) {
                    setState(() {
                      selectedPage = value;
                    });
                  },
                  email: _emailController.text,
                  password: _passwordController.text,
                  onTap: _handleEmail,
                )),
          if (selectedPage == 1) MaterialPage(child: Cart()),
          if (selectedPage == 2) const MaterialPage(child: Profile()),
          if (selectedPage == 3) const MaterialPage(child: CheckOut()),
        ],
        onPopPage: (route, result) {
          _logIn = false;
          selectedPage = 0;
          return route.didPop(result);
        },
      ),
    );
  }
}

below is the code for the screen from where I can navigate to any screen.


class Home extends StatefulWidget {
  Home({
    Key? key,
    required this.password,
    required this.onTap,
    required this.email,
    required this.selectedPage,
  }) : super(key: key);
  String email;
  String password;
  final ValueChanged<String> onTap;
  final ValueChanged<int> selectedPage;
  static const valueKey = const ValueKey("home");

  @override
  State<Home> createState() => _HomeState();
}

int selectedPage = 0;

class _HomeState extends State<Home> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.amber,
      appBar: AppBar(
        title: Text('${widget.email}: Home'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text("${widget.password}"),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    selectedPage = 1;
                  });
                },
                child: Text("go to CART")),
            ElevatedButton(onPressed: () {}, child: Text("go to LOGIN")),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    selectedPage = 2;
                  });
                },
                child: Text("go to PROFILE")),
            ElevatedButton(
                onPressed: () {
                  setState(() {
                    selectedPage = 3;
                  });
                },
                child: Text("go to CHECKOUT")),
          ],
        ),
      ),
    );
  }
}

Solution

  • As for your Home can be simpler:

    class MyButton {
      int? id;
      String? label;
    
    
      MyButton({
        this.id,
        this.label,
      })
    /// Add More logic here if you want to
    }
    
    class Home extends StatefulWidget {
      Home({
        Key? key,
        required this.password,
        required this.onTap,
        required this.email,
        required this.selectedPage,
      }) : super(key: key);
      String email;
      String password;
      final ValueChanged<String> onTap;
      final ValueChanged<int> selectedPage;
      static const valueKey = const ValueKey("home");
    
      @override
      State<Home> createState() => _HomeState();
    }
    
    int? selectedPage;
    
    class _HomeState extends State<Home> {
      List<MyButton>? _myButton = [
        MyButton(id: 0, label: 'Go to Cart'),
        MyButton(id: 1, label: 'Go to profile'),
        MyButton(id: 2, label: 'Go to something'),
      ];
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          backgroundColor: Colors.amber,
          appBar: AppBar(
            title: Text('${widget.email}: Home'),
          ),
          body: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              children: _myButton!.map((button) {
                return ElevatedButton(
                    onPressed: () {
                      super.setState(() =>selectedPage = button.id!);
                    },
                    child: Text(button.label!);
              } ).toList(),
            ),
          ),
        );
      }
    }
    

    as for navigation, I would recommend using the navigator method just to minimise complexity over time. I would propose:

    Navigator(
    
      pages: [
        MaterialPage(
            key: const ValueKey("login"), // Separate it
            child: _onSelectedPage(),
        ),
      ],
    ),
    
    
    dynamic _onSelectedPage() {
      switch(selectedPage) {
        case 0:
          if(_logIn) {
            return Home(
              selectedPage: (value) {},
              email: _emailController.text,
              password: _passwordController.text,
              onTap: _handleEmail,
            );
          }
    
          return Login(
            isLogin: (value) {},
            onTapOne: _handleEmail,
            onTapTwo: _handlePassword,
          );
    
        case 1:
          return Cart();
        
        case 2:
          return Profile();
    
        case 3:
          return CheckOut();
    
        default:
          break;
      }
    }