Flutter内のシンプルなSnackBarのステートフルウィジェットを表示したい。私のアプリケーションは、MaterialAppの新しいインスタンスをMyHomePageと呼ばれるステートフルウィジェットで作成します。
ShowSnackBar()メソッドでSnackBarを表示しようとしています。ただし、「」で失敗します。メソッド「showSnackBar」はnullで呼び出されました。
このコードの何が問題になっていますか?
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
@override
void initState() {
super.initState();
showInSnackBar("Some text");
}
@override
Widget build(BuildContext context) {
return new Padding(
key: _scaffoldKey,
padding: const EdgeInsets.all(16.0),
child: new Text("Simple Text")
);
}
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(
content: new Text(value)
));
}
}
解決策:
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter',
theme: new ThemeData(
primarySwatch: Colors.blue,
),
home: new Scaffold(body: new MyHomePage()),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key}) : super(key: key);
@override
_MyHomePageState createState() => new _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
showInSnackBar("Some text");
return new Padding(
padding: const EdgeInsets.all(16.0),
child: new Scaffold(
body: new Text("Simple Text")
)
);
}
void showInSnackBar(String value) {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text(value)
));
}
}
3つの問題があります。 1つ目は、どこにもScaffoldがないことです。Scaffoldウィジェットは、スナックバーの表示方法を知っているウィジェットです。 2つ目は、足場をつかむための鍵を持っているが、代わりに足場に置いたということです(足場にはスナックバーの知識がありません)。 3番目は、ビルドの前にinitStateが呼び出されるため、関連付けられているウィジェットが初期化される前にキーを使用したことです。
最も簡単な解決策は、MyAppウィジェットのhome
行を次のように変更することです。
home: new Scaffold(body: new MyHomePage()),
...そして__scaffoldKey
_のすべての言及を削除し、代わりに現在__scaffoldKey.currentState
_があるところでScaffold.of(context)
を使用します。
私の場合、このようなコードがありました(クラス状態)
final GlobalKey<ScaffoldState> _scaffoldKey = new GlobalKey<ScaffoldState>();
void showInSnackBar(String value) {
_scaffoldKey.currentState.showSnackBar(new SnackBar(content: new Text(value)));
}
しかし、scaffoldのキーをセットアップしませんでした。だからkey:_scaffoldKeyを追加すると
@override
Widget build(BuildContext context) {
return new Scaffold(
key: _scaffoldKey,
body: new SafeArea(
スナックバーが働き始める:)
スナックバーをゆらゆらと表示するより優れた、よりクリーンな方法があります。私はそれが難しい方法であると分かち合ったので、おそらく他の誰かに役立つでしょう。
メインアプリ部分を変更する必要はありません
_class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'MyApp',
theme: new ThemeData(
primarySwatch: Colors.orange),
home: new MainPage());
}
}
_
ページ状態コードは状況が変わる場所です
FlutterがScaffold.of(context).showSnackBar
を提供することは知っています。ただし、コンテキストはScaffoldを含むコンテキストではなく、Scaffoldの子孫のコンテキストである必要があります。エラーを回避するために、以下のように、Scaffoldの本体にBuildContextを使用し、変数に保存する必要があります。
_class MainPageState extends State<MainPage> {
BuildContext scaffoldContext;
@override
Widget build(BuildContext context) {
return new Scaffold(
backgroundColor: Colors.grey,
appBar: new AppBar(
title: const Text(APP_TITLE),
),
body: new Builder(builder: (BuildContext context) {
scaffoldContext = context;
return new Center(
child: new Text('Hello World', style: new TextStyle(fontSize: 32.0)),
);
}));
}
void createSnackBar(String message) {
final snackBar = new SnackBar(content: new Text(message),
backgroundColor: Colors.red);
// Find the Scaffold in the Widget tree and use it to show a SnackBar!
Scaffold.of(scaffoldContext).showSnackBar(snackBar);
}
}
_
これで、この関数をどこからでも呼び出すことができ、スナックバーが表示されます。たとえば、インターネット接続メッセージを表示するために使用しています。
私がやった、私のために働く:)
@override
Widget build(BuildContext context) {
return new Scaffold(
appBar: new AppBar(
title: new Text('Demo')
),
body: new Builder(
// Create an inner BuildContext so that the onPressed methods
// can refer to the Scaffold with Scaffold.of().
builder: (BuildContext context) {
return new Center(
child: new RaisedButton(
child: new Text('SHOW A SNACKBAR'),
onPressed: () {
Scaffold.of(context).showSnackBar(new SnackBar(
content: new Text('Hello!'),
));
},
),
);
},
),
);
}
initState
がbuild
の前に呼び出された_scaffoldKey.currentState
は、呼び出し時に初期化されていません。
ScaffoldState
からinitState
を取得できるかどうかわかりません。コードを変更する場合は、build
メソッドからスナックバーを表示できます:
Scaffold.of(context).showSnackBar(new SnackBar(new Text(value)));
誰かがinitState()
でSnackbar
を初期化しようとしている場合(言い換えると、ここでページがロードされるときが私の解決策です)。また、あなたはすでに_scaffoldKey
所定の位置に。
void initState() {
super.initState();
Future.delayed(Duration(seconds: 1)).then(
(_) => _displaySnackbar
);
}
// Display Snackbar
void get _displaySnackbar {
_scaffoldKey.currentState.showSnackBar(SnackBar(
duration: Duration(minutes: 1),
content: Text('Your snackbar message')
));
}
InitState()でSnackbarを初期化するには、レイアウトが構築された後に関数を実行できます。
void initState() {
super.initState();
WidgetsBinding.instance
.addPostFrameCallback((_) => _scaffoldKey.currentState.showSnackBar(SnackBar(content: Text("Your message here..")));}
Scaffold.of(context).showSnackBar(
SnackBar(content: Text("Thanks for using snackbar",
textAlign: TextAlign.center, style: TextStyle(fontSize: 16.0, fontWeight:
FontWeight.bold),), duration: Duration(seconds: 2), backgroundColor: Colors.red,)
);
これを使用できます:
_final _scaffoldKey = GlobalKey<ScaffoldState>();
@override
Widget build(BuildContext context) {
return Scaffold(
key: _scaffoldKey,
appBar: AppBar(
),
}
}
_
onPressed()
にこのコードを追加できます
__scaffoldKey.currentState.showSnackBar(
new SnackBar(
content: new Text('Hello this is snackbar!')
)
);
_