2017-09-10 7 views
0

下部のタブをクリックしたときにSnackBarウィジェットを表示したいと思います。例外は自明であるが、FlutterでSnackBarを表示する方法

I/flutter (4965): The following assertion was thrown while handling a gesture: 
I/flutter (4965): Scaffold.of() called with a context that does not contain a Scaffold. 
I/flutter (4965): No Scaffold ancestor could be found starting from the context that was passed to Scaffold.of(). This 
I/flutter (4965): usually happens when the context provided is from the same StatefulWidget as that whose build 
I/flutter (4965): function actually creates the Scaffold widget being sought. 
I/flutter (4965): There are several ways to avoid this problem. The simplest is to use a Builder to get a context that 
I/flutter (4965): is "under" the Scaffold. For an example of this, please see the documentation for Scaffold.of(): 
I/flutter (4965): https://docs.flutter.io/flutter/material/Scaffold/of.html 
I/flutter (4965): A more efficient solution is to split your build function into several widgets. This introduces a 
I/flutter (4965): new context from which you can obtain the Scaffold. In this solution, you would have an outer widget 
I/flutter (4965): that creates the Scaffold populated by instances of your new inner widgets, and then in these inner 
I/flutter (4965): widgets you would use Scaffold.of(). 
I/flutter (4965): A less elegant but more expedient solution is assign a GlobalKey to the Scaffold, then use the 
I/flutter (4965): key.currentState property to obtain the ScaffoldState rather than using the Scaffold.of() function. 
I/flutter (4965): The context used was: 
I/flutter (4965): MyHomePage(state: _MyHomePageState(603645610)) 

:アプリは次の例外をスローしかし

Scaffold.of(context).showSnackBar(new SnackBar(
       content: new Text("Live Clicked"), 
      )); 

:私はとしてそれを表示しようとしています。 MyHomePageウィジェットにScaffoldがあるので、なぜそれが発生しているのか分かりません。

完全なコードは:

import 'package:flutter/material.dart'; 

void main() { 
    runApp(new MyApp()); 
} 

class MyApp extends StatelessWidget { 
    // This widget is the root of your application. 
    @override 
    Widget build(BuildContext context) { 
    return new MaterialApp(
     title: 'App Name', 
     theme: new ThemeData(
     primarySwatch: Colors.blue, 
    ), 
     home: new MyHomePage(title: 'App Name'), 
    ); 
    } 
} 

class MyHomePage extends StatefulWidget { 
    MyHomePage({Key key, this.title}) : super(key: key); 

    final String title; 

    @override 
    _MyHomePageState createState() => new _MyHomePageState(); 
} 

class _MyHomePageState extends State<MyHomePage> { 
    var bottomBarLabels = [ 
    new DestinationLabel(
     icon: new Icon(Icons.live_tv), title: new Text("Live")), 
    new DestinationLabel(
     icon: new Icon(Icons.date_range), title: new Text("Matches")), 
    ]; 

    @override 
    Widget build(BuildContext context) { 
    void _handleBottomNavigationBarTap(int newValue) { 
     switch (newValue) { 
     case 0: 
      print("Live Clicked"); 
      Scaffold.of(context).showSnackBar(new SnackBar(
       content: new Text("Live Clicked"), 
      )); 
      break; 
     case 1: 
      print("Matches Clicked"); 
      break; 
     } 
    } 

    return new Scaffold(
     key: new Key("homepage"), 
     appBar: new AppBar(
     title: new Text(config.title), 
    ), 
     bottomNavigationBar: new BottomNavigationBar(
      labels: bottomBarLabels, onTap: _handleBottomNavigationBarTap), 
    ); 
    } 
} 

答えて

2

あなたはが足場を持っていますが、MyHomePageのではない上記の文脈。 ScaffoldはMyHomePageの子ですが、Scaffold.of(context)は親の親の足場にアクセスしようとしています。 あなたは何も持っていないので、クラッシュします。

おそらくBottomNavigationBarを新しいクラスにラップする必要があります。そのウィジェットのコンテキストを使ってScaffold.of(context)を実行します。

+0

コードで回答を更新できますか? –

1

現時点ではFlutterのバージョンをアップグレードすることはできませんが、はライブIconを押した場合にのみ表示しようとしています。

だから、その後、BuilderIconButtonをラップ代わりにIconButtonにライブIconを作り、BottomNavigationBaronTapプロパティを使用するのではなく、独自にそのonPressedプロパティを使用して、次のような何かをしたいことがあります。

new BottomNavigationBar(
      labels: [ 
      new DestinationLabel(title: new Text("Live"), 
       icon: new Builder(builder: (BuildContext context) { 
       return new IconButton(icon: new Icon(Icons.live_tv), 
        onPressed:() { 
         Scaffold.of(context).showSnackBar(
          new SnackBar(content: new Text("Live Clicked"))); 
        }); 
       }), 
      ), 
      new DestinationLabel(icon: new Icon(Icons.date_range), 
       title: new Text("Matches"),) 


      ], 
     ) 

これがベストプラクティスであるかどうかわかりませんが、私たちのフラッター達は、複数のクラスからより複雑なウィジェットを作成することを常に提案しています。

+0

動作しませんでした。エラーが発生しました: '引数タイプ 'Builder'をパラメータタイプ 'Icon'に割り当てることはできません –

1

_handleBottomNavigationBarTapメソッドをBuildContext引数に変更してください。次のように

void _handleBottomNavigationBarTap(int newValue, BuildContext context) { 
    ... 
} 

その後、あなたのbottomNavigationBar引数を変更:

bottomNavigationBar: new Builder(
    builder: (BuildContext context) { 
    return new BottomNavigationBar(
     labels: bottomBarLabels, 
     onTap: (index) => _handleBottomNavigationBarTap(index, context), 
    ); 
    } 
), 

をこれは、あなたがcontextの祖先であるScaffoldStateを見つけることができるようになりますScaffold.of(context)に呼び出すことを保証します。