Home > OS >  How to add one search bar use for two tabs in flutter?
How to add one search bar use for two tabs in flutter?

Time:10-06

At my mobile apps homepage i have tabbar with two tabs act as category. both of those tabs display a listview with content depends on the category. (for example, a listview of book with fiction and non-fiction category.) and i want to add a single search function to search a book regardless their category.

The problem is:

  1. One search bar can only search on one category. means the search bar can only search on fiction category. i try to add 2nd search bar in each tab but in result it act like the problem below

  2. that whenever i click on the 2nd tab and then click on search bar, it will automatically go back to first tabs which is the default tab.

Solution that i think of:

Is to add setState so the tabs doesnt move back to default tab whenever i click on the search bar, but i dont know how.

Here is my code:

     // Tab Bar MOF and CIDB
          Container(
            decoration: BoxDecoration(
              borderRadius: BorderRadius.only(
                bottomLeft: Radius.circular(16),
                bottomRight: Radius.circular(16)
              ),
              color: Theme.of(context).primaryColor,
            ),
            width: double.infinity,
            child: TabBar(
              controller: _tabController,
              indicatorSize: TabBarIndicatorSize.tab,
              indicatorPadding: EdgeInsets.all(6),
              indicator: const UnderlineTabIndicator(borderSide: BorderSide(color: Colors.red, width: 100.0),
              insets: EdgeInsets.fromLTRB(10.0, 0.0, 10.0, 42.0),
              ),
              unselectedLabelColor: Colors.grey,
              tabs: [
                Tab(child: Text('MOF', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w300, ))),
                Tab(child: Text('CIDB', style: TextStyle(fontSize: 20, fontWeight: FontWeight.w300)))
            ]
            ),
             ),
             SizedBox(
              height: 30,
             ),
          //Space for Tender Listview
          Expanded(
            child: Container(
              width: double.infinity,
              //Tender List tile
              child: TabBarView(
                controller: _tabController,
                children: [
                  //MOF List
                  Column(
                    children: [
                      Expanded(
                        child: ListView.builder(
                          physics: BouncingScrollPhysics(),
                          itemCount: MOFs.length,
                          itemBuilder: (context, index) {
                            final MOF = MOFs[index];
                          return Card(
                            margin: EdgeInsets.fromLTRB(15, 20, 15, 20),
                            child: InkWell(
                              onTap: (){},
                              child: Container(
                                margin: EdgeInsets.all(4),
                                height: 200,
                                decoration: BoxDecoration(borderRadius: BorderRadius.circular(12),
                                //color: Colors.blue
                                ),
                                child: Center(child: Text(MOF.title)),
                              ),
                            ),
                          );
                        }),
                      ),
                      Container(
                        //color: Colors.pink,
                        margin: EdgeInsets.fromLTRB(150, 10, 150, 10),
                        child: TextField(
                        controller: controller,
                        onChanged: searchMOF,
                        decoration: InputDecoration(
                          hintText: 'Search by Keyword',
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(20),
                            borderSide: BorderSide(color: Colors.green))
                        ),
                        ),
                      ),
                    ],
                  ),
                  //CIDB List
                  Column(
                    children: [
                      Expanded(
                        child: ListView.builder(
                          physics: BouncingScrollPhysics(),
                          itemCount: CIDBs.length,
                          itemBuilder: (context, index) {
                            final CIDB = CIDBs[index];
                          return Container(
                            margin: EdgeInsets.all(10),
                            height: 200,
                            width: 50,
                            decoration: BoxDecoration(borderRadius: BorderRadius.circular(20),
                            //color: Colors.purple
                            ),
                            child: InkWell(
                              onTap: (){},
                              child: Card
                              (child: Center(child: Text(CIDB.title))),
                            ),
                            //List testing
                          );
                        }),
                      ),
                      Container(
                        //color: Colors.pink,
                        margin: EdgeInsets.fromLTRB(150, 10, 150, 10),
                        child: TextField(
                        controller: controller,
                        onChanged: searchCIDB,
                        decoration: InputDecoration(
                          hintText: 'Search by Keyword',
                          border: OutlineInputBorder(
                            borderRadius: BorderRadius.circular(20),
                            borderSide: BorderSide(color: Colors.green))
                        ),
                        ),
                      ),
                    ],
                  ),
                ],
              ),
            ),
          ),
        ],
      ),
    );
  }

CodePudding user response:

You can make the search bar works globally by creating a parent stateful widget with search bar and child widget with tabs and tabs' body. In each tab body, you can check if search text field controller is not empty and if yes, you make only the books that contains search text appears and if no, you make the whole list appears

CodePudding user response:

the whole step is too wide. i'll suggest some outline.

Only visible children will be rendered in a listview. When a child is scrolled out of view, the associated element subtree, states and render objects are destroyed


  • second is the lifecycle. When you call setState it means flutter re-execute build method. the method below.
 @override
  Widget build(BuildContext context) {
    return

thats why, everytime you call setState, the tabs is back to first tab. because it execute build method from the begining.

  • how to avoid rebuild entire widget is: Separate into new class. eg:
class TabMOF extend StatelessWidget{
...
 @override
  Widget build(BuildContext context) {
    return your MOF list
...
class TabCIBD  extend StatelessWidget{
...
 @override
  Widget build(BuildContext context) {
    return your CIBD list

then use is as a widget in your main Screen

...
body : Column(
  children: [
   // here will be your search bar 
   ... 
   // next is your tabbar
   Container(
     child: TabBar(
        tabs: [tab1, tab2 ]
   )
    Expanded(
       child: TabBarView(
         children:[
           TabMOF(),
           TabCIBD(),
         ]
  ]

with this way, your tab will not rebuild. but you have to update the List data for each tab. if you need to rebuild your stateFullwidget tab, you can change the valuekey. article


actually its hard to explain very detail, hope you got what i mean. thank you

  • Related