Search code examples
flutterdartsearchbar

Failed assertion: line 168 pos 15: 'icon != null': is not true


I am creating a searchbar in flutter and while doing this I found the above error. It is showing icon != null. I can not understand why is it showing! Can anybody tell me how do I solve this. It is showing the below error:

════════ Exception caught by widgets library ═══════════════════════════════════════════════════════
The following assertion was thrown building Consumer<PatientDataNotifier>(dirty, dependencies: [_InheritedProviderScope<PatientDataNotifier>]):
'package:flutter/src/material/icon_button.dart': Failed assertion: line 168 pos 15: 'icon != null': is not true.
The relevant error-causing widget was: 
  Consumer<PatientDataNotifier> file:///F:/ShortedCubeSolutionProjects/flutter_data_table/lib/homescreen.dart:124:16
When the exception was thrown, this was the stack: 
#2      new IconButton (package:flutter/src/material/icon_button.dart:168:15)
#3      HomeScreen.build.<anonymous closure> (package:flutter_data_table/homescreen.dart:130:21)
#4      Consumer.buildWithChild (package:provider/src/consumer.dart:177:19)
#5      SingleChildStatelessWidget.build (package:nested/nested.dart:260:41)
#6      StatelessElement.build (package:flutter/src/widgets/framework.dart:4701:28)

Below is my code.

class HomeScreen extends StatelessWidget {
  String appBarTitle = 'Patient Details';
  TextEditingController nameController = TextEditingController();

  var icon;
  
  Widget bodyData(PatientDataNotifier patientDataNotifier, BuildContext context) {
    return SingleChildScrollView(
      scrollDirection: Axis.horizontal,
      child: Container(
        margin: EdgeInsets.only(top: 20.0, left: 10.0, right: 10.0),
        decoration: BoxDecoration(
          border: Border.all(width: 1.0, color: Colors.black),
        ),
        child: DataTable(
        //..........
      );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: PreferredSize(
        preferredSize: const Size.fromHeight(80),
        child: Consumer<PatientDataNotifier>(
          builder: (context,  patientDataNotifier, _){
            return AppBar(
              centerTitle: true,
              title: Text(appBarTitle),
              actions: [
                new IconButton(
                    icon: icon,
                    onPressed: (){
                      if(this.icon == Icons.search){
                        this.icon = new Icon(
                          Icons.close,
                          color: Colors.white,
                        );
                        this.appBarTitle = new TextFormField(
                          controller: nameController,
                          style: new TextStyle(
                              color: Colors.white
                          ),
                          decoration: new InputDecoration(
                            prefixIcon: Icon(Icons.search, color:  Colors.white),
                            hintText: 'Search..',
                            hintStyle: TextStyle(color:  Colors.white),
                          ),
                          onChanged: (text){
                            patientDataNotifier.getPatients(text);
                          },
                        ) as String;
                      }
                    }
                )
              ],
            );
          },

        ),
      ),
      body: Container(
        child: Consumer<PatientDataNotifier>(
          builder: (context, patientDataNotifier, _){
            return bodyData(patientDataNotifier, context);
          },
        ),
      ),
    );
  }
}

Please help me to do this! I am stuck!


Solution

  • The issue that you are having is that your icon is null and you cannot pass a null value to the child in the iconButton. You are using a stateless widget, but you should use a statefull because you want to reload the view when you change the value. I have changed a bit the logic so it will show one widget or another widget in your app when you are using the search bar.

    class HomeScreen extends StatefulWidget {
      @override
      _HomeScreenState createState() => _HomeScreenState();
    }
    
    class _HomeScreenState extends State<HomeScreen> {
    
      TextEditingController nameController = TextEditingController();
    
      bool textField;
    
      @override
      void initState() {
        super.initState();
        this.textField = false;
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: PreferredSize(
            preferredSize: const Size.fromHeight(80),
            child: AppBar(
              centerTitle: true,
              title: textField ? new TextFormField(
                controller: nameController,
                style: new TextStyle(
                    color: Colors.white
                ),
                decoration: new InputDecoration(
                  prefixIcon: Icon(Icons.search, color:  Colors.white),
                  hintText: 'Search..',
                  hintStyle: TextStyle(color:  Colors.white),
                ),
                onChanged: (text){
                },
              ) : Text('Patient Details'),
              actions: [
                new IconButton(
                    icon: textField ? new Icon(
                      Icons.close,
                      color: Colors.white,
                    ) : Icon(Icons.search),
                    onPressed: (){
                      setState(() {
                        this.textField = !this.textField;
                      });
                    }
                )
              ],
            ),
          ),
        );
      }
    }
    

    If you are creating a search bar I would recommend you to use the search delegate.