Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Flutter navigation for part of screen

How can I push a widget in the frame of another widget? For example I have a Column with 2 Containers where every Container takes half of the screen. I'd like to make a navigation e.g. only in the bottom container. The same logic as in iOS when the container view has it's own UINavigationController.

As I understood MaterialPageRoute can push widgets only to fullscreen and there aren't any other Route classes, except abstract ones. Maybe I should make my own subclass of ModalRoute/TransitionRoute?

like image 417
FashionYeti Avatar asked Jun 22 '18 10:06

FashionYeti


3 Answers

You can use Navigator as a child for the specific part you want to make that. And I used WillPopScope to go back to the previous screen if there is one. and make sure to use GlobalKey() to separate each navigator and give it a unique key. My code :

var keyOne = GlobalKey<NavigatorState>();
var keyTwo = GlobalKey<NavigatorState>();
return Column(
  children: [
    Expanded(
      child: Container(
        child: WillPopScope(
          onWillPop: () async => !await keyOne.currentState.maybePop(),
          child: Navigator(
            key: keyOne,
            onGenerateRoute: (routeSettings) {
              return MaterialPageRoute(
                builder: (context) => ScreenOne(),
              );
            },
          ),
        ),
      ),
    ),
    Expanded(
      child: Container(
        child: WillPopScope(
          onWillPop: () async => !await keyTwo.currentState.maybePop(),
          child: Navigator(
            key: keyTwo,
            onGenerateRoute: (routeSettings) {
              return MaterialPageRoute(
                builder: (context) => ScreenTwo(),
              );
            },
          ),
        ),
      ),
    ),
  ],
);
like image 97
Khaled Mahmoud Avatar answered Sep 27 '22 16:09

Khaled Mahmoud


You can use the Navigator widget to provide any number of individual navigators in your app. Each Navigator will maintain it's own navigation stack. For example, if you wanted to split your app vertically with each half having it's own navigation stack:

Column(
  children: <Widget>[
    Navigator(...),
    Navigator(...)
  ]
)

If you do this, you should consider how you want to handle the Android back button (now that you technically have 3 navigators in your app). By default, it will only listen to your root navigator so you will have to provide a WillPopScope widget somewhere in your widget hierarchy to capture back button events and pop from the appropriate navigator.

like image 43
Kirollos Morkos Avatar answered Sep 27 '22 18:09

Kirollos Morkos


One possible solution would be to create a new MaterialApp on that portion of the screen and handle everything from there like a regular app (just with different screen size) like so:

Column(
        children: <Widget>[
          Container(
            height: constraints.maxHeight * 0.5,
            width: constraints.maxWidth,
          ),
          Container(
              height: constraints.maxHeight * 0.5,
              width: constraints.maxWidth,
              child: MaterialApp(
                  debugShowCheckedModeBanner: false,
                  theme: ThemeData(
                    primaryColor: Color.fromRGBO(86, 86, 86, 1.00),
                  ),
                  initialRoute: '/W1',
                  routes: {
                    '/W1': (context) => WidgetOne(),
                    '/W2': (context) => WidgetTwo(),
                  })),
        ],
      ),

Then handle the routing from withing the widgets like so:

class WidgetOne extends StatelessWidget {
@override
Widget build(BuildContext context) {
  return GestureDetector(
    onTap: () {
      Navigator.pushNamed(context, '/W2');
    },
    child: Container(color: Colors.green));
    }
  }
}

class WidgetTwo extends StatelessWidget {
@override
Widget build(BuildContext context) {
  return GestureDetector(
    onTap: () {
      Navigator.pushNamed(context, '/W1');
    },
    child: Container(color: Colors.pink));
    }
  }
}

Result: https://i.stack.imgur.com/qyJ5N.gif

like image 28
Yodart Avatar answered Sep 27 '22 16:09

Yodart