如何在Flutter中获取当前上下文?

12

我正在使用底部导航栏。在某个事件触发时,我需要在当前屏幕上显示一些警报。

这是我实现底部导航栏的方式。我有四个选项卡。 在这里,当_isHomeDetected为真并且用户点击图标(即索引3)时,我需要更改第4个选项卡的图标,无论用户在哪个选项卡中,都要显示警报消息。 我该怎么做?

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???");
      }
    });
  }
}

1
我不明白问题出在哪里。我在你的代码中找不到你在文本中提到的大多数东西。你到底在哪里无法引用“context”? - Günter Zöchbauer
由于您的显示警报对话框的代码位于构建方法内部,因此您始终可以访问它。 - Napolean
3个回答

5

声明一个全局键(global key)

final globalNavigatorKey = GlobalKey<NavigatorState>();

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

然后将这个全局键分配给您的 MaterialApp

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

然后你只需要在需要的地方调用示例:

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

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

3

7
在State类中的任何位置都可以。State有一个context成员/获取器。 - wamfous
3
链接已经失效,有人拥有这个例子吗? - progNewbie
@progNewbie 这个链接对我有用:link ... 尽管我不确定它是否仍然演示了 GlobalKey 的使用! - Andy King
1
谢谢您的回答...它解决了我的问题:如果有人正在寻找细节:// 1 GlobalKey _scaffoldMessengerKey = GlobalKey(); // 2 MaterialApp( scaffoldMessengerKey: _scaffoldMessengerKey, ) // 3 _scaffoldMessengerKey.currentState.showSnackBar(....) - Jobin Jacob Kavalam

2

进一步解释一下@Ron Geo的答案:

请注意,只有在以下情况下才应考虑此答案: 您尝试从中调用showSnackBar的小部件不是MaterialApp的子级。

例如,下面就是这种情况:

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

现在,如果您想让 App 小部件显示一个 Snackbar,可以执行以下操作:

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(....);
  }
}

需要重申的是,在大多数情况下,如果您调用showSnackBar的widget已经是MaterialApp的子级,则不需要使用此解决方案...在这种情况下,以下代码将简单地工作:

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接