Search code examples
androidflutterdropdowntabbar

only static members can be accessed in initializers when adding dropdownbutton to tab


my app contains TapView, one of these tabs contains a DropDownButton, when creating the DropDownButton it reject it and produce and error that only static member can be accessed in initializers

so i tried to initialize it inside the initState() and invoke it in tap like here but it gives me Null pointer exception:

class _MyHomePageState extends State<MyHomePage> {

  static DropdownButton<ExpenseType> drop ;
  ExpenseType Drop_value = new ExpenseType("tt", Icons.directions_bus);
  List<ExpenseType> DropDownValues = new List<ExpenseType>();
  void onChange_Drop(ExpenseType value){
    setState(() {
      Drop_value = value;
    });
  }


  @override
  void initState() {


    drop =  new DropdownButton(value:Drop_value,
        items: DropDownValues.map((ExpenseType value){
          return new DropdownMenuItem(
              value: value,
              child: Row(
                children: <Widget>[
                  new Text(value.expType),
                ],
              ));
        }).toList(),
        onChanged: (ExpenseType value){onChange_Drop(value);});
    DropDownValues.addAll([
       ExpenseType("transportation",Icons.directions_bus),
       ExpenseType("food",Icons.fastfood),
       ExpenseType("drink",Icons.local_drink),
       ExpenseType("shopping",Icons.shopping_basket),
       ExpenseType("others",Icons.menu),
    ]);

    Drop_value = DropDownValues.elementAt(0);
    super.initState()
}

  List<Widget> containers = [
    Container(
      child: new SingleChildScrollView(
        // the main content container
        child: new Column(
          children: <Widget>[
//Type container
                            new Column(
                              children: <Widget>[
                                new Text(
                                  "hello",
                                  textAlign: TextAlign.left,
                                  style: new TextStyle(color: Colors.black),
                                  textDirection: TextDirection.ltr,
                                ),
                                drop,

                              ],
                            ),
                          ],
                        ),
    Container(),
    Container(),
  ];
  @override
  Widget build(BuildContext context) {
    // This method is rerun every time setState is called, for instance as done
    // by the _incrementCounter method above.
    //
    // The Flutter framework has been optimized to make rerunning build methods
    // fast, so that you can just rebuild anything that needs updating rather
    // than having to individually change instances of widgets.
    return DefaultTabController(
      length: 3,
      child: Scaffold(
        appBar: new AppBar(
          // Here we take the value from the MyHomePage object that was created by
          // the App.build method, and use it to set our appbar title.

          title: Center(
            child: Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: <Widget>[
                new Icon(
                  Icons.monetization_on,
                  color: Colors.black,
                ),
                new Text(" Expensia"),
              ],
            ),
          ),
          bottom: TabBar(
            tabs: <Widget>[
              Tab(
                text: "Add",
              ),
              Tab(
                text: "Prev Expenses",
              ),
              Tab(
                text: "Statistics",
              ),
            ],
          ),
        ),
        body: TabBarView(children: containers),
      ),
    );
  }
}

Solution

  • Your containers List as well as your DropdownButton should really be instantiated in your build function. This ensures all your widgets get rebuilt when Flutter requires it (on setState() for example).

    Here is a bit of a modified version of yours that should work if you just replace with your model classes (String's in mine)

    class _MyHomePageState extends State<MyHomePage> {
      String dropValue;
      List<String> dropDownValues;
    
      void onChangeDrop(String value) {
        setState(() {
          dropValue = value;
        });
      }
    
      @override
      void initState() {
        dropDownValues = [
          "transportation",
          "food",
          "drink",
          "shopping",
          "others",
        ];
    
        dropValue = dropDownValues[0];
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return DefaultTabController(
          length: 3,
          child: Scaffold(
            appBar: new AppBar(
              title: Center(
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    new Icon(
                      Icons.monetization_on,
                      color: Colors.black,
                    ),
                    new Text(" Expensia"),
                  ],
                ),
              ),
              bottom: TabBar(
                tabs: <Widget>[
                  Tab(text: "Add"),
                  Tab(text: "Prev Expenses"),
                  Tab(text: "Statistics"),
                ],
              ),
            ),
            body: TabBarView(children: [
              Container(
                  child: new SingleChildScrollView(
                      child: new Column(
                children: <Widget>[
                  new Column(
                    children: <Widget>[
                      new Text(
                        "hello",
                        textAlign: TextAlign.left,
                        style: new TextStyle(color: Colors.black),
                        textDirection: TextDirection.ltr,
                      ),
                      DropdownButton(
                          value: dropValue,
                          items: dropDownValues.map((String value) {
                            return new DropdownMenuItem(
                                value: value, child: new Text(value));
                          }).toList(),
                          onChanged: (String value) {
                            onChangeDrop(value);
                          }),
                    ],
                  ),
                ],
              ))),
              Container(),
              Container(),
            ]),
          ),
        );
      }
    }