Search code examples
flutterdarttabsrefreshtabbar

TabBar without changing state of first tab and refresh second tab


I have a widget TabBar on the main page with two tabs - page1() and page2(). In page1() I have DropdownSearch and in Page2() ListView. When I choose something on Page1, I can see it on Page2 (I use AutomaticKeepAliveClientMixin). But when I come back to Page1, my DropdownSearch resets. How I can save the state on the first page and not reset the chosen value in my Dropdown?

I used also AutomaticKeepAliveClientMixin but with bool get wantKeepAlive => false; but it doesn't work

class Page1 extends StatefulWidget {

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

class _Page1State extends State<Page1>
    with AutomaticKeepAliveClientMixin<Page1> {

   ...
 @override
 Widget build(BuildContext context) {
    super.build(context);

  return Center(
  child:
   DropdownSearch<Object>(
            mode: Mode.MENU,
            isFilteredOnline: true,
            showClearButton: true,
            items: list,
            showSearchBox: true,

            dropdownSearchDecoration: InputDecoration(
              contentPadding: EdgeInsets.symmetric(horizontal: 14),
              labelText: "Choose",
              hintText: "something",
            ),

            //autoValidate: true,
            validator: (u) =>
            u == null ? "field is required " : null,

            onChanged: (data) {
              if(data != null) {
                print(data);
              }
            },
          ),
      )
   )
  ...

  @override
  bool get wantKeepAlive => false;
}


class Page2 extends StatefulWidget {

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

class _Page2State extends State<Page2>
    with AutomaticKeepAliveClientMixin<Page2> {

...

  @override
  bool get wantKeepAlive => true;
}

Solution

  • I have 100% working and reusable solution for this:) You can keep this is as a separate file:

    import 'package:flutter/material.dart';
    
    class KeepPageAlive extends StatefulWidget {
      const KeepPageAlive({
        Key? key,
         this.child,
      }) : super(key: key);
    
      final Widget? child;
    
      @override
      _KeepPageAliveState createState() => _KeepPageAliveState();
    }
    
    class _KeepPageAliveState extends State<KeepPageAlive>
        with AutomaticKeepAliveClientMixin {
      @override
      Widget build(BuildContext context) {
        super.build(context);
    
        return widget.child!;
      }
    
      @override
      bool get wantKeepAlive => true;
    }
    

    and you need to just wrap your tab_page widget with this class:

    Column(
              children: [
                SimpleTabBar(
                  tabController: _tabController,
                  tabTitles: [
                    LocaleKeys.byCargo.tr(),
                    LocaleKeys.byCar.tr(),
                    LocaleKeys.byCompany.tr(),
                  ],
                  onTabTapped: onTabTapped,
                ),
                Flexible(
                  child: PageView(
                    controller: _pageController,
                    onPageChanged: onPageChanged,
                    children: [
                      KeepPageAlive(child: SearchCargoPostsLayout()),
                      KeepPageAlive(child: SearchTruckPostsLayout()),
                      KeepPageAlive(child: SearchCompaniesLayout()),
                    ],
                  ),
                ),
              ],
            ),