Chaythanya Nair
Chaythanya Nair

Reputation: 5064

How to get the current context in Flutter?

I am using a bottom navigation bar. On a certain Event trigger I need to show some alert on the current screen.

This is how I have implemented the bottom navigation bar. I have four tabs. Here, I need to change the icon of the 4th tab when _isHomeDetected is true and when the user clicks on the icon, i.e on index 3 I have to show an alert message irrespective of which tab the user is in. How do I do this?

class LandingScreen extends StatefulWidget {
  static Widget bottomNavigationBar;
  ..
}

class _LandingScreenState extends State<LandingScreen> {
  ...
  StreamSubscription<String> _subscription;
  bool _isHomeDetected = false;

  @override
  void initState() {
    ...
    _subscription = server.messages.listen(onData, onError: onError);
  }
  onData(message) {
    setState(() {
      _isHomeDetected = json.decode(message)["isHomeBeacon"];
    });
  }
  ...
  @override
  Widget build(BuildContext context) {
    LandingScreen.bottomNavigationBar = new BottomNavigationBar(
        ....
    );
    return new Scaffold(
      body: _currentPage,
      bottomNavigationBar: LandingScreen.bottomNavigationBar,
    );
  }

  _navigateToScreens(int currentIndex) {
    List screens = [
      ..
    ];
    setState((){

      if (!_isHomeDetected || currentIndex != 3){
        _currentPage = screens[currentIndex];
      } else {
        Utils.showCupertinoAlert(
            context: context, content: "You wanna log out???");
      }
    });
  }
}

Upvotes: 12

Views: 35255

Answers (3)

Ilyas Arafath
Ilyas Arafath

Reputation: 681

Declare a global key

final globalNavigatorKey = GlobalKey<NavigatorState>();

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  runApp(MyApp());
}

then assign this global key to your MaterialApp

return MaterialApp(
          title: 'Flutter Demo',
          navigatorKey: globalNavigatorKey,
          theme: ThemeData(primarySwatch: Colors.blue,),
          home: MyHomePage(),
);

then wherever you want just call example : -

const snackBar = SnackBar(content: Text('Yay! A SnackBar!'));

ScaffoldMessenger.of(globalNavigatorKey.currentContext).showSnackBar(snackBar);

Upvotes: 6

Jobin Jacob Kavalam
Jobin Jacob Kavalam

Reputation: 141

Just to elaborate on the answer given by @Ron Geo:

Please note that this answer should be considered if your situation is one where: The widget you are trying to call showSnackBar from isn't a child of MaterialApp.

As an example, this is the case below:

class App extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp();
  }
}

Now, if you want App widget to show a snackbar, the following can be done:

class App extends StatelessWidget {
  // 1
  GlobalKey<ScaffoldMessengerState> _scaffoldMessengerKey = GlobalKey();

  @override
  Widget build(BuildContext context) {
    return MaterialApp( 
      // 2
      scaffoldMessengerKey: _scaffoldMessengerKey,
    );
  }

  // 3
  void showSnackBar() {
     _scaffoldMessengerKey.currentState.showSnackBar(....);
  }
}

Just to re-iterate this solution is NOT required in most cases where the widget you are calling showSnackBar from is already a child of MaterialApp ... in that case the following code will simply work:

class MyPage extends StatelessWidget {
  void showSnackBar() {
     ScaffoldMessenger.of(context).showSnackBar(....);
  }
}

Upvotes: 2

Ron Geo
Ron Geo

Reputation: 31

Within the build method of any stateful widget you'll be able to get the build context. If you can't do this, the below sample from flutter team uses a GlobalKey<ScaffoldState> to hace access to show snackBar alert.

https://github.com/flutter/flutter/blob/master/examples/flutter_gallery/lib/demo/cupertino/cupertino_alert_demo.dart

Upvotes: 3

Related Questions