Как правильно отобразить Snackbar во Flutter?

Я пытаюсь показать Snackbar при нажатии floatingActionbutton. Но когда я нажимаю floatingactionbutton, он ничего не показывает. Вот мой код. Я использую StatefulWidget. Я отлаживал и проверял, что функция onPressed также выполняется, но почему-то Snackbar не отображается. В чем может быть основная причина проблемы? Я чувствую, что у BuildContext, который я передаю, есть проблема.

class MyApp extends StatefulWidget{
  @override
  MyAppState createState() {
    // TODO: implement createState
    return new MyAppState();
  }

}

class MyAppState extends State<MyApp>{
  File _image;
  String _text;

  Future getImage() async {
    var image = await ImagePicker.pickImage(source: ImageSource.camera);
    _image = image;
    final FirebaseVisionImage visionImage = FirebaseVisionImage.fromFile(_image);
    final TextRecognizer textRecognizer = FirebaseVision.instance.textRecognizer();
    final VisionText visionText = await textRecognizer.processImage(visionImage);

    String detectedText = visionText.text;

    setState(() {
      _image = image;
      _text = detectedText;
    });
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: new AppBar(
          title: new Text('Image Picker Example'),
        ),
        body: new Center(
          child: _image == null
              ? new Text('No image selected.')
              : new Image.file(_image),
        ),
        floatingActionButton: new FloatingActionButton(
          onPressed: (){
            showSnackBar(context);
//            getImage();
          },
          tooltip: 'Pick Image',
          child: new Icon(Icons.add_a_photo),
        ),
      ),
    );
  }

  void showSnackBar(BuildContext context) {
    final scaffold = Scaffold.of(context);
    final snackBarContent = SnackBar(
      content: Text("sagar"),
      action: SnackBarAction(
          label: 'UNDO', onPressed: scaffold.hideCurrentSnackBar),
    );
    scaffold.showSnackBar(snackBarContent);
  }

}

person sagar suri    schedule 25.12.2018    source источник


Ответы (2)


Это происходит потому, что используемый BuildContext не имеет Scaffold предка, поэтому он не сможет найти его для рендеринга SnackBar, поскольку его отображение зависит от Scaffold.

Согласно документации метода:

Когда Scaffold фактически создается в той же функции сборки, контекстный аргумент функции сборки не может использоваться для поиска Scaffold (поскольку он находится над возвращаемым виджетом). В таких случаях можно использовать следующую технику с Builder, чтобы предоставить новую область с BuildContext, которая находится под Scaffold:

@override
Widget build(BuildContext context) {
  return Scaffold(
    appBar: AppBar(
      title: Text('Demo')
    ),
    body: Builder(
      // Create an inner BuildContext so that the onPressed methods
      // can refer to the Scaffold with Scaffold.of().
      builder: (BuildContext context) {
        return Center(
          child: RaisedButton(
            child: Text('SHOW A SNACKBAR'),
            onPressed: () {
              ScaffoldMessenger.of(context).showSnackBar(SnackBar(
                content: Text('Hello!'),
              ));
            },
          ),
        );
      },
    ),
  );
}

Решение

Обертывание FloatingActionButton в виджет Builder сделает это возможным более элегантным способом, чем использование GlobalKey, о котором уже упоминалось в ответе @Epizon.

person Miguel Ruivo    schedule 25.12.2018

Чтобы показать SnackBar, вы можете использовать это так:

 ScaffoldMessenger.of(context).showSnackBar(SnackBar(
          content: Text('User Logged In'),
        ));

Предыдущий SnackBar использовался так:

Scaffold.of(context).showSnackBar(SnackBar(
                content: Text('Rahul Kushwaha!'),
              ));

Теперь SnackBar управляется ScaffoldMessenger. Для получения подробной информации изучите эту ссылку.

person Rahul Kushwaha    schedule 04.02.2021