Search code examples
flutterrouteswidgetpushnavigator

How to push a widget with Navigator into only a portion of the screen?


I have the device screen divided in two, a top view and a bottom view. I would like to push a new view with a Navigator from the BottomView by doing: Navigator.of(context).pushNamed('/nameHere'). However, I need the new view to be pushed in place of only the bottom view, not the entire screen, as it happens instead.

Here's my main.dart:

void main() {
  runApp(
    MaterialApp(
      darkTheme: ThemeData(),
      initialRoute: homeRoute,
      routes: {
        homeRoute: (context) => const HomeView(),
        newViewRoute: (context) => const NewView(),
      },
    ),
  );
}

my HomeView:

class HomeView extends StatelessWidget {
  const HomeView({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: SafeArea(
        bottom: false,
        child: Column(
          children: [
            const Expanded(
              child TopView(),
            ),
            const Expanded(
              child: BottomView(),
            )
          ],
        ),
      ),
    );
  }
}

and my BottomView, where I push the new view, which I'd like to appear only in the bottom part of the screen:

class BottomView extends StatelessWidget {
  const BottomView({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: ElevatedButton(
        onPressed: () {
          Navigator.of(context)
          .pushNamed(newViewRoute);
        }
      )
    );
  }
}

Thanks to everybody for helping!


Solution

  • Solution

    This solution Does not require any external library

    If you need the top widget to be fixed and the navigation to replace only the bottom screen, you can create a base widget that would wrap the whole widget, and this base widget would not be affected by the flutter navigator.

    Example

    Create a baseview like this

    class BaseView extends StatelessWidget {
      const BaseView({super.key, required this.child});
      final Widget child;
      @override
      Widget build(BuildContext context) {
        return Column(
          children: [
            TopView(), // the top view that does not change
            child, // child widget that changes
          ],
        );
      }
    }
    

    Your main.dart should include the BaseView in the builder as shown below

    void main() {
      runApp(
        MaterialApp(
          darkTheme: ThemeData(),
          initialRoute: homeRoute,
          builder: (context, child) => BaseView(child: child!),
          routes: {
            homeRoute: (context) => const BottomRoute1(),
            newViewRoute: (context) => const BottomRoute2(),
          },
        ),
      );
    }
    
    

    with this solution, all the routes you create would be rendered on the bottom of the screen and using the default flutter navigation changes the bottom widgets. This can be used to create fixed top or bottom navigations for mobile applications or flutter websites.

    I hope this solves your problem.

    Exceptions

    if you get an error like this while navigating using named routes error while navigating

    add a navigator key in the main.dart

    GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
    
    void main() {
      runApp(
        MaterialApp(
          darkTheme: ThemeData(),
          navigatorKey: navigatorKey, // add navigator key to material app
          initialRoute: homeRoute,
          builder: (context, child) => BaseView(child: child!),
          routes: {
            homeRoute: (context) => const BottomRoute1(),
            newViewRoute: (context) => const BottomRoute2(),
          },
        ),
      );
    }
    
    

    You can now use this navigator in your app to navigate as follows

    navigatorKey.currentState!.pushNamed(routeName);
    

    This should solve any problem you have. You can checkout my project built using this method here

    Happy coding 😀👍