skip to Main Content

I have the suggestions list displayed on the screen by default, and I would like to make the suggestions list shows only when clicking on the text field.

I tried to put the listView in side the setState, but it did not work. I also tried to make a controller listener, but also did not work. Should I wrap the listView with a button?

Any help please!

here is my code

class MySearchBar extends StatefulWidget {
  const MySearchBar({super.key});

  @override
  State<MySearchBar> createState() => _MySearchBarState();
}

class _MySearchBarState extends State<MySearchBar> {
  final myController = TextEditingController();
  static List<RestaurantProfiles> searchList = mySearchList;

  List<RestaurantProfiles> display_list = List.from(searchList);

  // this is the function that will update the suggestion list while searching
  void searchUpdate(String value) {
    setState(() {
      display_list = searchList
          .where((element) => element.restaurantName
              .toLowerCase()
              .contains(value.toLowerCase()))
          .toList();
    });
  }

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(40),
      child: Column(
        mainAxisAlignment: MainAxisAlignment.start,
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          const SizedBox(
            height: 20,
          ),
          TextField(
            onChanged: (value) => searchUpdate(value),
            style: const TextStyle(
              color: Colors.black,
            ),
            decoration: InputDecoration(
              filled: true,
              fillColor: Colors.white,
              isDense: true,
              contentPadding: const EdgeInsets.all(10),
              border: OutlineInputBorder(
                borderRadius: BorderRadius.circular(30),
                borderSide: BorderSide.none,
              ),
              hintText: "Add Restaurants",
              hintStyle: const TextStyle(
                color: Colors.black26,
              ),
              prefixIcon: const Icon(Icons.search),
              prefixIconColor: Colors.black,
            ),
          ),
          const SizedBox(
            height: 5,
          ),
          SizedBox(
            height: 250,
            child: Expanded(
              child: display_list.isEmpty
                  ? const Center(
                      child: Text(
                        "oops... No Results Found!",
                        style: TextStyle(
                          fontSize: 20,
                        ),
                      ),
                    )
                  : Container(
                      decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(10),
                          color: Colors.white70),
                      child: ListView.builder(
                        itemCount: display_list.length,
                        itemBuilder: (context, index) => ListTile(
                          contentPadding: const EdgeInsets.all(8),
                          title: Text(display_list[index].restaurantName),
                          leading: Image(
                            image: AssetImage(display_list[index].img),
                            fit: BoxFit.cover,
                            height: 50,
                            width: 50,
                          ),
                          trailing: const Icon(Icons.add),
                        ),
                      ),
                    ),
            ),
          ),
        ],
      ),
    );
  }
} 

2

Answers


  1. I have created a sample based on your code. I hope this will resolve the issue.

    class MySearchBar extends StatefulWidget {
      const MySearchBar({super.key});
    
      @override
      State<MySearchBar> createState() => _MySearchBarState();
    }
    
    class _MySearchBarState extends State<MySearchBar> {
      final myController = TextEditingController();
      // static List<RestaurantProfiles> searchList = mySearchList;
      final mySearchList = ['abc', 'xyz', 'cvb'];
      List display_list = [];
    
      // this is the function that will update the suggestion list while searching
      void searchUpdate(String value) {
        setState(() {
          display_list = mySearchList
              .where(
                  (element) => element.toLowerCase().contains(value.toLowerCase()))
              .toList();
        });
      }
    
      FocusNode node = FocusNode();
      @override
      void initState() {
        super.initState();
    
        node.addListener(() {
          showList = node.hasFocus;
          setState(() {});
        });
      }
    
      TextEditingController textEditingController = TextEditingController();
      bool showList = false;
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          body: Padding(
            padding: const EdgeInsets.all(40),
            child: Column(
              mainAxisAlignment: MainAxisAlignment.start,
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                const SizedBox(
                  height: 20,
                ),
                TextField(
                  controller: textEditingController,
                  focusNode: node,
                  onChanged: (value) => searchUpdate(value),
                  style: const TextStyle(
                    color: Colors.black,
                  ),
                  decoration: InputDecoration(
                    filled: true,
                    fillColor: Colors.white,
                    isDense: true,
                    contentPadding: const EdgeInsets.all(10),
                    border: OutlineInputBorder(
                      borderRadius: BorderRadius.circular(30),
                      borderSide: BorderSide.none,
                    ),
                    hintText: "Add Restaurants",
                    hintStyle: const TextStyle(
                      color: Colors.black26,
                    ),
                    prefixIcon: const Icon(Icons.search),
                    prefixIconColor: Colors.black,
                  ),
                ),
                const SizedBox(
                  height: 5,
                ),
                SizedBox(
                  height: 250,
                  child: Expanded(
                    child: showList || textEditingController.text.isNotEmpty
                        ? display_list.isEmpty
                            ? const Center(
                                child: Text(
                                  "oops... No Results Found!",
                                  style: TextStyle(
                                    fontSize: 20,
                                  ),
                                ),
                              )
                            : Container(
                                decoration: BoxDecoration(
                                    borderRadius: BorderRadius.circular(10),
                                    color: Colors.white70),
                                child: ListView.builder(
                                  itemCount: display_list.length,
                                  itemBuilder: (context, index) => ListTile(
                                    contentPadding: const EdgeInsets.all(8),
                                    title: Text(display_list[index]),
                                    // leading: Image(
                                    //   image: AssetImage(display_list[index].img),
                                    //   fit: BoxFit.cover,
                                    //   height: 50,
                                    //   width: 50,
                                    // ),
                                    trailing: const Icon(Icons.add),
                                  ),
                                ),
                              )
                        : Text('Search for restaurant'),
                  ),
                ),
              ],
            ),
          ),
        );
      }
    }
    
    Login or Signup to reply.
  2. First off, I’d like to mention that you’d probably want to use a SearchDelegate instead – as it can suggest the results for completion.

    You can use a FocusNode to listen to changes. it detects when the TextField does/desn’t have focus.

    At your State class, create 3 variables:

    class _MySearchBarState extends State<MySearchBar> {
      final myController = TextEditingController();
      final _focusNode = FocusNode();
      var _isSearching = false;
    

    Then, create an initState method:

     @override
      void initState() {
        super.initState();
        _focusNode.addListener(() {
          setState(() {
            _isSearching = _focusNode.hasFocus;
          });
        });
      }
    

    And in your listview.builder:

    Container(
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                            color: Colors.white70),
                        child: _isSearching
                            ? ListView.builder(
                                itemCount: display_list.length,
                                itemBuilder: (context, index) {
                                  return Text(
                                    'test',
                                    style: TextStyle(color: Colors.black),
                                  );
                                  return ListTile(
                                    contentPadding: const EdgeInsets.all(8),
                                    title: Text(display_list[index].restaurantName),
                                    leading: Image(
                                      image: AssetImage(display_list[index].img),
                                      fit: BoxFit.cover,
                                      height: 50,
                                      width: 50,
                                    ),
                                    trailing: const Icon(Icons.add),
                                  );
                                },
                              )
                            : Container(),
                      )
    

    Complete runnable snippet:

    import 'package:flutter/material.dart';
    
    void main() => runApp(MyApp());
    
    class MyApp extends StatelessWidget {
      @override
      Widget build(BuildContext context) {
        return MaterialApp(
          title: 'Material App',
          home: Scaffold(
            appBar: AppBar(
              title: Text('Material App Bar'),
            ),
            body: MySearchBar(),
          ),
        );
      }
    }
    
    class MySearchBar extends StatefulWidget {
      const MySearchBar({super.key});
    
      @override
      State<MySearchBar> createState() => _MySearchBarState();
    }
    
    class _MySearchBarState extends State<MySearchBar> {
      final myController = TextEditingController();
      final _focusNode = FocusNode();
      var _isSearching = false;
      static List<RestaurantProfiles> searchList = [
        RestaurantProfiles('test', 'assets/images/restaurant1.jpg'),
      ];
    
      List<RestaurantProfiles> display_list = List.from(searchList);
    
      // this is the function that will update the suggestion list while searching
      void searchUpdate(String value) {
        setState(() {
          display_list = searchList
              .where((element) => element.restaurantName
                  .toLowerCase()
                  .contains(value.toLowerCase()))
              .toList();
        });
      }
    
      @override
      Widget build(BuildContext context) {
        return Padding(
          padding: const EdgeInsets.all(40),
          child: Column(
            mainAxisAlignment: MainAxisAlignment.start,
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const SizedBox(
                height: 20,
              ),
              TextField(
                focusNode: _focusNode,
                onChanged: (value) => searchUpdate(value),
                style: const TextStyle(
                  color: Colors.black,
                ),
                decoration: InputDecoration(
                  filled: true,
                  fillColor: Colors.white,
                  isDense: true,
                  contentPadding: const EdgeInsets.all(10),
                  border: OutlineInputBorder(
                    borderRadius: BorderRadius.circular(30),
                    borderSide: BorderSide.none,
                  ),
                  hintText: "Add Restaurants",
                  hintStyle: const TextStyle(
                    color: Colors.black26,
                  ),
                  prefixIcon: const Icon(Icons.search),
                  prefixIconColor: Colors.black,
                ),
              ),
              const SizedBox(
                height: 5,
              ),
              Expanded(
                child: display_list.isEmpty
                    ? const Center(
                        child: Text(
                          "oops... No Results Found!",
                          style: TextStyle(
                            fontSize: 20,
                          ),
                        ),
                      )
                    : Container(
                        decoration: BoxDecoration(
                            borderRadius: BorderRadius.circular(10),
                            color: Colors.white70),
                        child: _isSearching
                            ? ListView.builder(
                                itemCount: display_list.length,
                                itemBuilder: (context, index) {
                                  return Text(
                                    'test',
                                    style: TextStyle(color: Colors.black),
                                  );
                                  return ListTile(
                                    contentPadding: const EdgeInsets.all(8),
                                    title: Text(display_list[index].restaurantName),
                                    leading: Image(
                                      image: AssetImage(display_list[index].img),
                                      fit: BoxFit.cover,
                                      height: 50,
                                      width: 50,
                                    ),
                                    trailing: const Icon(Icons.add),
                                  );
                                },
                              )
                            : Container(),
                      ),
              ),
            ],
          ),
        );
      }
    
      @override
      void initState() {
        super.initState();
        _focusNode.addListener(() {
          setState(() {
            _isSearching = _focusNode.hasFocus;
          });
        });
      }
    }
    
    class RestaurantProfiles {
      final String restaurantName;
      final String img;
    
      RestaurantProfiles(this.restaurantName, this.img);
    }
    
    

    Relatable

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search