Ad

Keyboard Suddenly Disappears Of TextField

- 1 answer

I have created a page in which there is search bar and then the listview builder which is building items of List coming from provider class. When I tap on search bar, the keyboard appears ,suddenly disappears and page refreshes. when page is refreshed, first it shows circularprogressIndicator and then regular ListView.builder. Kindly Help. Thank you in advance!

import 'package:carstraders/models/cars.dart';
import 'package:carstraders/providers/cars_provider.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class SearchPage extends StatefulWidget {
  static const routeName = 'search-page';

  const SearchPage({Key? key}) : super(key: key);

  @override
  _SearchPageState createState() => _SearchPageState();
}

class _SearchPageState extends State<SearchPage> {
  var search = TextEditingController();
  var list = [];
  List<Cars> allItems = [];
  String query = '';

  bool isFirstTime = true;

  @override
  void initState() {
    allItems = Provider.of<CarsProvider>(context, listen: false).list;
    list = allItems;
    // TODO: implement initState
    super.initState();
  }

this is the function which searches the items and updates the list

  void searchItem(String val) {
    final searched = allItems.where((element) {
      final transmission = element.transmission.toLowerCase();
      final model = element.model.toLowerCase();
      final make = element.make.toLowerCase();
      final price = element.price.toString();
      final engine = element.engine.toString();
      final searchedVal = val.toLowerCase();
      if (model.contains(searchedVal) ||
          make.contains(searchedVal) ||
          price.contains(searchedVal) ||
          engine.contains(searchedVal) ||
          transmission.contains(searchedVal)) {
        return true;
      }
      return false;
    }).toList();
    setState(() {
      list = searched;
      query = val;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Search'),
      ),
      body: FutureBuilder(
        future: Provider.of<CarsProvider>(context,listen: false).fetchAndSet(),
        builder: (ctx, snap) => snap.connectionState == ConnectionState.waiting
            ? const Center(
                child: CircularProgressIndicator(),
              )
            : Column(children: [
                Row(
                  children: [
                    Expanded(
                      child: Padding(
                        padding: const EdgeInsets.all(8.0),
                        child: TextField(
                          onChanged: searchItem,
                          // style: TextStyle(color: Colors.white),
                          controller: search,
                          key: const Key('search'),
                          keyboardType: TextInputType.emailAddress,
                          decoration: InputDecoration(
                            label: const Text('Search'),
                            suffixIcon: query.isEmpty
                                ? null
                                : GestureDetector(
                                    child: const Icon(Icons.close),
                                    onTap: () {
                                      setState(() {
                                        query = '';
                                        searchItem('');
                                        search.clear();
                                        FocusScope.of(context).unfocus();
                                      });
                                    },
                                  ),
                            prefixIcon: const Icon(Icons.search_sharp),
                            enabledBorder: const OutlineInputBorder(
                              borderSide: BorderSide(
                                color: Colors.grey,
                                width: 0.5,
                              ),
                            ),
                          ),
                        ),
                      ),
                    ),
                  ],
                ),
                Expanded(
                  child: ListView.builder(
                    itemBuilder: (ctx, i) => buildItem(list[i], context),
                    itemCount: list.length,
                  ),
                )
              ]),
      ),
    );
  }
}

this widget builds the item of listview.builder

Widget buildItem(Cars item, BuildContext context) {
  return GestureDetector(
    onTap: () =>
        Navigator.of(context).pushNamed('search-item-detail', arguments: item),
    child: Card(
      elevation: 5,
      child: Row(
        // mainAxisAlignment: MainAxisAlignment.start,
        children: [
          SizedBox(
            width: MediaQuery.of(context).size.width * 0.43,
            child: Image.network(item.img),
          ),
          SizedBox(width: MediaQuery.of(context).size.width * 0.02),
          Column(
            children: [
              Text(
                item.year.toString() + ' ' + item.make + ' ' + item.model,
                style: const TextStyle(
                  color: Colors.blueAccent,
                ),
              ),
              SizedBox(
                  width: MediaQuery.of(context).size.width * 0.5,
                  child: const Divider(color: Colors.black)),
              Row(
                children: [
                  Text('${item.mileage} mi'),
                  Container(
                      margin: EdgeInsets.symmetric(
                          horizontal: MediaQuery.of(context).size.width * 0.03),
                      decoration: const BoxDecoration(
                          border: Border(left: BorderSide(color: Colors.grey))),
                      child: const Text('')),
                  Text('£${item.price}')
                ],
              ),
              SizedBox(
                  width: MediaQuery.of(context).size.width * 0.5,
                  child: const Divider(color: Colors.black)),
              Row(
                children: [
                  Text('   ' + item.plateNo),
                  Container(
                    margin: EdgeInsets.symmetric(
                        horizontal: MediaQuery.of(context).size.width * 0.03),
                    child: const Text(''),
                    decoration: const BoxDecoration(
                        border: Border(left: BorderSide(color: Colors.grey))),
                  ),
                  Text(item.transmission)
                ],
              )
            ],
          )
        ],
      ),
    ),
  );
}
Ad

Answer

future builder trigger on every build. so when you click on searchBox the keyboard changes screen size and Expanded rebuild futureBuilder.


Solution Easy way .

Replace below part of future Builder

Column
  row
  Expanded
    listView.Builder

with

ListView.builder(
   itemBuilder: (ctx, i) {
    if(i==0){
      return row  
    }
    return buildItem(list[i -1], context)

   },
   itemCount: list.length + 1,
),
 

I think your code can write better. if you use bloc pattern or Riverpod pattern(similar to provider and has same author) so please look at this links

Ad
source: stackoverflow.com
Ad