web-dev-qa-db-fra.com

Scaffold.of () appelé avec un contexte qui ne contient pas d'échafaudage

Comme vous pouvez le voir, mon bouton est à l'intérieur du corps de Scaffold. Mais je reçois cette exception:

Scaffold.of () appelé avec un contexte qui ne contient pas d'échafaud.

import 'package:flutter/material.Dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: HomePage(),
    );
  }
}

class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('SnackBar Playground'),
      ),
      body: Center(
        child: RaisedButton(
          color: Colors.pink,
          textColor: Colors.white,
          onPressed: _displaySnackBar(context),
          child: Text('Display SnackBar'),
        ),
      ),
    );
  }
}

_displaySnackBar(BuildContext context) {
  final snackBar = SnackBar(content: Text('Are you talkin\' to me?'));
  Scaffold.of(context).showSnackBar(snackBar);
}

MODIFIER:

J'ai trouvé une autre solution à ce problème. Si nous attribuons une clé GlobalKey à Scaffold, nous pouvons afficher la barre Snack comme suit sans qu'il soit nécessaire d'envelopper notre corps avec le widget Builder. Le widget qui renvoie Scaffold devrait être un widget avec état cependant:

 _scaffoldKey.currentState.showSnackBar(snackbar); 
71
Figen Güngör

Cette exception se produit parce que vous utilisez la context du widget qui instanciait Scaffold. Pas le context d'un enfant de Scaffold.

Vous pouvez résoudre ce problème en utilisant simplement un contexte différent:

Scaffold(
    appBar: AppBar(
        title: Text('SnackBar Playground'),
    ),
    body: Builder(
        builder: (context) => 
            Center(
            child: RaisedButton(
            color: Colors.pink,
            textColor: Colors.white,
            onPressed: () => _displaySnackBar(context),
            child: Text('Display SnackBar'),
            ),
        ),
    ),
);

Notez que si nous utilisons Builder ici, ce n’est pas le seul moyen d’obtenir un BuildContext différent.

Il est également possible d'extraire le sous-arbre dans un autre Widget (généralement à l'aide de extract widget refactor)

101
Rémi Rousselet

Vous pouvez utiliser un GlobalKey. Le seul inconvénient est que GlobalKey peut ne pas être le moyen le plus efficace de le faire.

Une bonne chose à ce sujet est que vous pouvez également transmettre cette clé à d'autres classes de widgets personnalisés ne contenant aucun échafaudage. Voir ( ici )

class HomePage extends StatelessWidget {
  final _scaffoldKey = GlobalKey<ScaffoldState>(); \\ new line
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      key: _scaffoldKey,                           \\ new line
      appBar: AppBar(
        title: Text('SnackBar Playground'),
      ),
      body: Center(
        child: RaisedButton(
          color: Colors.pink,
          textColor: Colors.white,
          onPressed: _displaySnackBar(context),
          child: Text('Display SnackBar'),
        ),
      ),
    );
  }
}

_displaySnackBar(BuildContext context) {
  final snackBar = SnackBar(content: Text('Are you talkin\' to me?'));
  _scaffoldKey.currentState.showSnackBar(snackBar);   \\ edited line
}
47
Lebohang Mbele

Vérifiez ceci dans la documentation de la méthode:

Lorsque l'échafaudage est réellement créé dans la même fonction de génération, l'argument contextuel de la fonction de génération ne peut pas être utilisé pour trouver l'échafaud (puisqu'il est "au-dessus" du widget renvoyé). Dans de tels cas, la technique suivante avec un générateur peut être utilisée pour fournir une nouvelle portée avec un BuildContext qui est "sous" l'échafaudage:

@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: () {
              Scaffold.of(context).showSnackBar(SnackBar(
                content: Text('Hello!'),
              ));
            },
          ),
        );
      },
    ),
  );
}

Vous pouvez vérifier la description à partir de la de la méthode docs

4
SANAT

Un moyen simple de résoudre ce problème sera de créer une clé pour votre échafaudage, comme celle-ci, avec le code suivant:

_scaffoldKey = GlobalKey<ScaffoldState>(); et appelez votre snackBar à l’aide de l’opérateur point.

_scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Welcome")));

1