Search code examples
flutterdartstatetextfield

State updating itself when focusing TextField - Flutter


I am trying to make a screen with filter, and a search buttons, but whenever i select a text field the screen start searching, even if i haven't written anything yet, i am using a column with 2 textFields, none of them uses onChanged or onTap functions, after the textfields, there is a button, where i wanted to do the search, and after the button there's a future builder, where the info is suposed to show.

Padding(
  padding: const EdgeInsets.all(8.0),
  child: TextFormField(
    controller: ctrl1,
    keyboardType: TextInputType.number,
    inputFormatters: [FilteringTextInputFormatter.digitsOnly],
    decoration: const InputDecoration(
      border: OutlineInputBorder(),
      fillColor: Colors.white,
      labelText: 'filter1',
      floatingLabelBehavior: FloatingLabelBehavior.always,
    ),
  ),
),
Padding(
  padding: const EdgeInsets.all(8.0),
  child: TextFormField(
    controller: ctrl2,
    decoration: const InputDecoration(
      border: OutlineInputBorder(),
      fillColor: Colors.white,
      labelText: 'filter2',
      floatingLabelBehavior: FloatingLabelBehavior.always,
    ),
  ),
)

Whenever i tap or change any of the text fields, apparently the state updates, forcing the search. How can i stop the textfields from updating the state of the Screen when tapped or changed?


Solution

  • I resolved the issue by using this variable Future<List<dynamic>?>? infoList; as the future in FutureBuilder, and when the search button is pressed, i just update this var with the search function like this infoList = search(filter1.text, filter2.text);.

    class _WidgSttflState extends State<WidgSttfl> {
      TextEditingController ctrl1 = TextEditingController(),
          ctrl2 = TextEditingController();
      PageController _pgView = PageController(initialPage: 0);
      ExpansionTileController exp = ExpansionTileController();
      Future<List<dynamic>?>? infoList;
    
      Future<dynamic> buildData(filter1, filter2) async {
        ...
      }
    
      Future<List<dynamic>?> search(filter1, filter2) async {
        return await buildData(filter1, filter2);
      }
      
      @override
      void initState() {
        infoList = Future.value([]);
        super.initState();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          appBar: AppBar(
            title: 'title'
          ),
          body: PageView(
            controller: _pgView,
            physics: const NeverScrollableScrollPhysics(),
            children: [
              ...,
              Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                children: [
                  Theme(
                    data: Theme.of(context).copyWith(
                      dividerColor: Colors.transparent,
                    ),
                    child: ExpansionTile(
                      title: const Text('Filters'),
                      controller: exp,
                      initiallyExpanded: true,
                      leading: Row(
                        mainAxisSize: MainAxisSize.min,
                        children: [
                          IconButton(
                            onPressed: () => _pgView.previousPage(
                              duration: const Duration(seconds: 1),
                              curve: Curves.easeInOutCubicEmphasized,
                            ),
                            icon: const Icon(
                              Icons.arrow_back,
                              color: Colors.orange,
                            ),
                          ),
                          const VerticalDivider(
                            thickness: 1,
                            indent: 5,
                            endIndent: 5,
                            color: Colors.orange,
                          ),
                        ],
                      ),
                      trailing: const Icon(Icons.filter_alt),
                      children: [
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: TextFormField(
                            controller: ctrl1,
                            keyboardType: TextInputType.number,
                            inputFormatters: [
                              FilteringTextInputFormatter.digitsOnly
                            ],
                            decoration: const InputDecoration(
                              border: OutlineInputBorder(),
                              fillColor: Colors.white,
                              labelText: 'filter1',
                              floatingLabelBehavior: FloatingLabelBehavior.always,
                            ),
                          ),
                        ),
                        Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: TextFormField(
                            controller: ctrl2,
                            decoration: const InputDecoration(
                              border: OutlineInputBorder(),
                              fillColor: Colors.white,
                              labelText: 'filter2',
                              floatingLabelBehavior: FloatingLabelBehavior.always,
                            ),
                          ),
                        ),
                        ...,
                        SizedBox(
                          width: double.infinity,
                          child: Padding(
                            padding: const EdgeInsets.fromLTRB(8, 0, 8, 0),
                            child: ElevatedButton(
                              onPressed: () {
                                setState(() {
                                  infoList = search(filter1.text, filter2.text);
                                  exp.collapse();
                                });
                              },
                              child: const Text(
                                'Search',
                                style: TextStyle(
                                  color: Colors.white,
                                  fontWeight: FontWeight.bold,
                                ),
                              ),
                            ),
                          ),
                        ),
                      ],
                    ),
                  ),
                  const Divider(thickness: 2),
                  Expanded(
                    child: FutureBuilder(
                      future: infoList,
                      builder: (context, snapshot) {
                        if (snapshot.connectionState == ConnectionState.waiting) {
                          return const Center(child: CircularProgressIndicator());
                        } else if (snapshot.hasData) {
                          if (snapshot.data.isNotEmpty) {
                            return ListView.separated(
                              itemCount: snapshot.data.length,
                              separatorBuilder: (context, index) =>
                                  const Divider(),
                              itemBuilder: (context, index) {
                                return ListTile(
                                  title: Text(''),
                                  subtitle: Text(''),
                                );
                              },
                            );
                          }
                        }
                      },
                    ),
                  ),
                ],
              ),
            ],
          ),
        );
      }
    }