Flutter-- How to add a search bar to search in the list

841 Views Asked by At

I have a countries list which shows the time for the countries. Please let me know how to add the search bar.You can see the WorldTime list in the code. So it's displaying the countries name with the image. The code is as follows.

Choose_Location.dart

class  Chooselocation extends StatefulWidget {
      @override
      _ChooseLocationState createState() => _ChooseLocationState();
    }
    
    class _ChooseLocationState extends State<Chooselocation> {
    
      List<WorldTime> locations =[
      WorldTime(url:'Europe/London', location: 'London', flag: 'England.png'),
      WorldTime(url:'Europe/Berlin', location: 'Berlin', flag: 'Germany.jpg'),
      WorldTime(url:'Africa/Cairo', location: 'Cairo', flag: 'Egypt.jpg'),
      WorldTime(url:'Africa/Nairobi', location: 'Nairobi', flag: 'Kenya.jpg'),
      WorldTime(url:'Asia/Jakarta', location: 'Seoul', flag: 'Indonesia.jpg'),
      WorldTime(url:'Asia/Qatar', location: 'Qatar', flag: 'Qatar.png'),
      WorldTime(url:'Africa/Khartoum', location: 'Sudan', flag: 'Sudan.jpg'),
      WorldTime(url:'Asia/Karachi', location: 'Pakistan', flag: 'Pakistan.png'),
      WorldTime(url:'America/New_York', location: 'USA', flag: 'USA.jpg'),
           
      ];
    
    
      void updatetime(index) async{
      WorldTime instance = locations[index];
      await instance.getTime();
      // mnavigate to home screen
      Navigator.pop(context,{
    'location':instance.location,
    'flag':instance.flag,
    'time':instance.time,
    'isDaytime':instance.isDaytime,
    
      });
      }
     
     
      @override
      Widget build(BuildContext context) {
        print('Build state function');
        return Scaffold(
           
          backgroundColor: Colors.blueGrey[200],
          appBar: AppBar(
          title:Text('Choose a Location'),
          centerTitle:true,
          elevation:0,
          ),
    
          body: ListView.builder(
            itemCount:locations.length,
            itemBuilder: (context,index){
              return Padding(
                padding: const EdgeInsets.symmetric(vertical:1.0, horizontal: 4.0),
                child: Card(child: ListTile(
                  onTap: (){
                    updatetime(index);
                    print(locations[index].location);
    
                  },
                  title:Text(locations[index].location),
                  leading: CircleAvatar(
                    backgroundImage: AssetImage('assets/${locations[index].flag}')),
                ),
                ),
              );
            }      
          ),
        );
      }    
    }

You can see the image of the UI below.

LocationList

2

There are 2 best solutions below

0
On

In my case, i don't have WorldTime model class, so i used List<String> for filter functionality. You can use your model class for filter your list.

class Chooselocation extends StatefulWidget {
  @override
  _ChooseLocationState createState() => _ChooseLocationState();
}

class _ChooseLocationState extends State<Chooselocation> {
  List<String> locations = [
    'London',
    'Berlin',
    'Cairo',
    'Nairobi',
    'Seoul',
    'Qatar',
    'Sudan',
    'Pakistan',
    'USA'
  ];
  List<String> locationList;
  var locationDataList = List<String>();

  final TextEditingController _filter = TextEditingController();
  String _searchText = "";
  Icon _searchIcon = new Icon(Icons.search);
  Widget _appBarTitle;

  void _searchPressed(String title) {
    setState(() {
      if (this._searchIcon.icon == Icons.search) {
        this._searchIcon = new Icon(Icons.close);
        this._appBarTitle = new TextField(
          style: setTextStyle(),
          controller: _filter,
          decoration: new InputDecoration(
              focusedBorder: UnderlineInputBorder(
                  borderSide: BorderSide(color: Colors.white)),
              prefixIcon: new Icon(
                Icons.search,
                color: Colors.white,
              ),
              hintText: 'Search...',
              hintStyle: setTextStyle()),
        );
      } else {
        this._searchIcon = new Icon(Icons.search);
        this._appBarTitle = new Text(title);
        _filter.clear();
        this._appBarTitle = null;
      }
    });
  }

  setTextStyle() {
    return TextStyle(color: Colors.white);
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    print("object");
    _filter.addListener(() {
      if (_filter.text.isEmpty) {
        setState(() {
          _searchText = "";
          updateFilter(_searchText);
        });
      } else {
        setState(() {
          _searchText = _filter.text;
          updateFilter(_searchText);
        });
      }
    });
  }

  void updateFilter(String text){
    print("updated Text: ${text}");
    filterSearchResults(text);
  }

  void filterSearchResults(String query) {
    List<String> dummySearchList = List<String>();
    dummySearchList.addAll(locationList);
    print("List size : " + dummySearchList.length.toString());
    if(query.isNotEmpty) {
      List<String> dummyListData = List<String>();
      dummySearchList.forEach((item) {
        if(item.toLowerCase().contains(query.toLowerCase())) {
          dummyListData.add(item);
        }
      });
      setState(() {
        locationDataList.clear();
        locationDataList.addAll(dummyListData);
      });
      return;
    } else {
      setState(() {
        locationDataList.clear();
        locationDataList.addAll(locations);
      });
    }
  }

  @override
  Widget build(BuildContext context) {

    if (locationList == null) {
      locationList = List<String>();
      locationList.addAll(locations);
      locationDataList.addAll(locationList);
    }

    return Scaffold(
      backgroundColor: Colors.blueGrey[200],
      appBar: AppBar(
        actions: <Widget>[
          IconButton(
            icon: _searchIcon,
            onPressed: () {
              _searchPressed("Choose Location");
            },
            tooltip: "Search",
          )
        ],
        title: _appBarTitle == null ? Text('Choose a Location') : _appBarTitle,
        centerTitle: true,
        elevation: 0,
      ),
      body: ListView.builder(
          itemCount: locationDataList.length,
          itemBuilder: (context, index) {
            return Padding(
              padding:
                  const EdgeInsets.symmetric(vertical: 1.0, horizontal: 4.0),
              child: Card(
                child: ListTile(
                  title: Text(locationDataList[index]),
                  leading: CircleAvatar(),
                ),
              ),
            );
          }),
    );
  }
}

Output of above code would be :

Output

Hope this may help you :)

0
On

Create a TextField for enter searchKey by user

Use:

List<WorldTime> filteredLocations = locations.where(element => element.location == **searchKey**).toList();

Its return a list of all elements that contains searhchKey