skip to Main Content

How to not rebuild the screen from start in the bottom navigation bar and saving the last state of it and if the state of the screen is changed like the driver app has 4 screens and I want the screen of home that contains button Offline Now or Online Now not change the state if I move to another screen, I used a Tabviewbar

What is the solution?

Main Screen class

import 'package:drivers_app/tabsPages/earnings_tab_screen.dart';
import 'package:drivers_app/tabsPages/home_tab_screen.dart';
import 'package:drivers_app/tabsPages/profile_tab_screen.dart';
import 'package:drivers_app/tabsPages/zones_tab_page.dart';
import 'package:flutter/material.dart';

class MainScreen extends StatefulWidget
{
  static const String mainScreenId = "mainScreenId";

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

class _MainScreenState extends State<MainScreen> with SingleTickerProviderStateMixin
{
  TabController? tabController;

  int selectedIndex = 0;

  void onItemClicked(int index)
  {
    setState(()
    {
      selectedIndex = index;
      tabController!.index = selectedIndex;
    });
  }

  @override
  void initState() {
    // TODO: implement initState
    super.initState();

    tabController = TabController(length: 4, vsync: this);
  }

  @override
  void dispose() {
    // TODO: implement dispose
    super.dispose();
    tabController!.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold
    (
      body: TabBarView(
        physics: NeverScrollableScrollPhysics(),
        controller: tabController,
        children:
        [
          HomeScreen(),
          EarningsScreen(),
          ZonesScreen(),
          ProfileScreen(),
        ],
        //index: selectedIndex,
      ),
      bottomNavigationBar: BottomNavigationBar(
        items:
        [
          BottomNavigationBarItem(
            icon: Icon(
                Icons.home,
              ),
            label: 'Home',
          ),
          BottomNavigationBarItem(
            icon: Icon(
                Icons.credit_card,
              ),
            label: 'Earnings',
          ),
          BottomNavigationBarItem(
            icon: Icon(
                Icons.settings_input_antenna_rounded,
              ),
            label: 'Zones',
          ),
          BottomNavigationBarItem(
            icon: Icon(
                Icons.person,
              ),
            label: 'Account',
          ),
        ],
        unselectedItemColor: Colors.black54,
        selectedItemColor: Colors.blue,
        type: BottomNavigationBarType.fixed,
        selectedLabelStyle: TextStyle(
          fontSize: 12.0
        ),
        showUnselectedLabels: true,
        currentIndex: selectedIndex,
        onTap: onItemClicked,
      ),
    );
  }
}


Home Screen Class

import 'package:drivers_app/shared/components/components.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:flutter/material.dart';
import 'package:flutter_geofire/flutter_geofire.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';

class HomeScreen extends StatefulWidget
{
  static final CameraPosition _kGooglePlex = CameraPosition(
    target: LatLng(37.42796133580664, -122.085749655962),
    zoom: 15,
  );

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  Completer<GoogleMapController> _controllerGoogleMap = Completer();

  GoogleMapController? newcontrollerGoogleMap;

  var geoLocator = Geolocator();

  String driverStatusText = 'Offline Now - Go Online ';

  Color driverStatusColor = Colors.black;

  bool isDriverAvailable = false;


  @override
  void initState()
  {
    super.initState();
    getCurrentDriverInfo();
  }

  void locatePosition() async
  {
    Position position = await Geolocator.getCurrentPosition(desiredAccuracy: LocationAccuracy.high);
    currentPosition = position;

    LatLng latLatPosition = LatLng(position.latitude, position.longitude);

    CameraPosition cameraPosition = CameraPosition(target: latLatPosition, zoom: 14);
    newcontrollerGoogleMap!.animateCamera(CameraUpdate.newCameraPosition(cameraPosition));

    String Address = await AssistantMethods.searchCoordinateAddress(position, context);
    print("This is your Address :: " + Address);

  }


  void getCurrentDriverInfo() async
  {
    currentfirebaseUser = await FirebaseAuth.instance.currentUser;
    
    driversRef.child(currentfirebaseUser!.uid).once().then((DataSnapshot dataSnapshot)
    {
      if(dataSnapshot.value != null)
      {
        driversInformation = Drivers.fromSnapshot(dataSnapshot);
      }
    });
    
    PushNotificationService pushNotificationService = PushNotificationService();

    pushNotificationService.initialize(context);
    pushNotificationService.getToken().toString();
    
    AssistantMethods.retrieveHistoryInfo(context);
  }

  @override
  Widget build(BuildContext context)
  {
    return Stack(
      children:
      [
        GoogleMap(
          mapType: MapType.normal,
          myLocationButtonEnabled: true,
          initialCameraPosition: HomeScreen._kGooglePlex,
          myLocationEnabled: true,
          onMapCreated: (GoogleMapController controller) {
            _controllerGoogleMap.complete(controller);
            newcontrollerGoogleMap = controller;
            _determinePosition();
          },
        ),

        //online offline driver container
        Container(
          height: 140.0,
          width: double.infinity,
          color: Colors.black54,
        ),
        Positioned(
          top: 60.0,
          left: 0.0,
          right: 0.0,
          child: Row(
            mainAxisAlignment: MainAxisAlignment.center,
            children:
            [
              Padding(padding: EdgeInsets.symmetric(
                horizontal: 16.0,
              ),
                child: MaterialButton(
                  onPressed: ()
                  {
                    if(isDriverAvailable != true)
                    {
                      makeDriverOnlineNow();
                      getLocationLiveUpdates();

                      setState(()
                      {
                        driverStatusColor = Colors.green;
                        driverStatusText = 'Online Now ';
                        isDriverAvailable = true;
                      });
                      displayToast('you are Online Now', context);
                    }
                    else
                    {
                      displayToast('you are Offline Now', context);
                      setState(()
                      {
                        driverStatusColor = Colors.black;
                        driverStatusText = 'Offline Now - Go Online ';
                        isDriverAvailable = false;
                      });
                      makeDriverOfflineNow();
                      Appclosed();
                    }
                  },
                  color: driverStatusColor,
                  child: Padding(
                    padding: EdgeInsets.all(17.0,),
                    child: Row(
                      mainAxisAlignment: MainAxisAlignment.spaceBetween,
                      children: [
                        Text(
                          driverStatusText,
                          style: TextStyle(
                            fontSize: 20.0,
                            fontWeight: FontWeight.bold,
                            color: Colors.white,
                          ),
                        ),
                        Icon(
                          Icons.phone_android,
                          color: Colors.white,
                          size: 26.0,
                        ),
                      ],
                    ),
                  ),
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }

Main class

import 'package:drivers_app/config_maps.dart';
import 'package:drivers_app/modules/car_info_screen.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:firebase_database/firebase_database.dart';
import 'package:firebase_messaging/firebase_messaging.dart';
import 'package:flutter/material.dart';
import 'package:drivers_app/Data_Handler/app_Data.dart';
import 'package:drivers_app/modules/login_screen.dart';
import 'package:drivers_app/modules/main_screen.dart';
import 'package:provider/provider.dart';
import 'package:drivers_app/modules/register_screen.dart';

//Receive message when app is in background solution for on message
Future<void> backgroundHandler(RemoteMessage message) async
{
  print(message.data.toString());
  print(message.notification!.title);
}


void main() async{
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();

  FirebaseMessaging.onBackgroundMessage(backgroundHandler);


  currentfirebaseUser = FirebaseAuth.instance.currentUser;
  runApp(MyApp());
}

DatabaseReference adminRef = FirebaseDatabase.instance.reference().child("admin");
DatabaseReference driversRef = FirebaseDatabase.instance.reference().child("drivers");
DatabaseReference newRequestRef = FirebaseDatabase.instance.reference().child("Ride Request");
DatabaseReference rideRequestRef = FirebaseDatabase.instance.reference().child("drivers").child(currentfirebaseUser!.uid).child("newRide");
DatabaseReference availableDriverRef = FirebaseDatabase.instance.reference().child("availableDrivers");
DatabaseReference availableDriverRef2 = FirebaseDatabase.instance.reference().child("availableDrivers2").child(currentfirebaseUser!.uid);


class MyApp extends StatelessWidget {

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return ChangeNotifierProvider(
      create:(context) => AppData(),
      child: MaterialApp(
        title: 'Driver App',
        debugShowCheckedModeBanner: false,
        theme: ThemeData(
          primarySwatch: Colors.blue,
          visualDensity: VisualDensity.adaptivePlatformDensity,
        ),
        initialRoute: FirebaseAuth.instance.currentUser == null ? LoginScreen.loginScreenId : MainScreen.mainScreenId,
        routes:{
          RegisterScreen.registerScreenId: (context)=> RegisterScreen(),
          LoginScreen.loginScreenId: (context)=> LoginScreen(),
          MainScreen.mainScreenId: (context)=> MainScreen(),
          CarInfoScreen.carinfoScreen: (context)=> CarInfoScreen(),
        },
      ),
    );
  }
}

2

Answers


  1. You can use a PageView and AutomaticKeepAliveClientMixin on each page/portion (item in the PageView) and set wantToKeepAlive to true.

    For example:

    If we have 2 portions, HomePortion and SettingsPortion like so:

    class HomePortion extends StatefulWidget {
      const HomePortion({Key? key}) : super(key: key);
    
      @override
      _HomePortionState createState() => _HomePortionState();
    }
    
    class _HomePortionState extends State<HomePortion>
        with AutomaticKeepAliveClientMixin {
      @override
      Widget build(BuildContext context) {
        super.build(context);
        return const Center(
          child: Text("Home"),
        );
      }
    
      @override
      bool get wantKeepAlive => true;
    }
    
    class SettingsPortion extends StatefulWidget {
      const SettingsPortion({Key? key}) : super(key: key);
    
      @override
      _SettingsPortionState createState() => _SettingsPortionState();
    }
    
    class _SettingsPortionState extends State<HomePortion>
        with AutomaticKeepAliveClientMixin {
      @override
      Widget build(BuildContext context) {
        super.build(context);
        return const Center(
          child: Text("Settings"),
        );
      }
    
      @override
      bool get wantKeepAlive => true;
    }
    

    Notice @override bool get wantKeepAlive => true; in both portions.

    We can then use them in the Page like so:

    class DashboardPage extends StatefulWidget {
      const DashboardPage({Key? key}) : super(key: key);
    
      @override
      _DashboardPageState createState() => _DashboardPageState();
    }
    
    class _DashboardPageState extends State<DashboardPage> {
      @override
      Widget build(BuildContext context) {
        return Scaffold(
          bottomNavigationBar: BottomNavigationBar(
            onTap: (index) {
              _controller.jumpToPage(index);
              setState(() {
                _pageIndex = index;
              });
            },
            currentIndex: _pageIndex,
            items: const [
              BottomNavigationBarItem(
                icon: Icon(Icons.home_rounded),
              ),
              BottomNavigationBarItem(
                icon: Icon(Icons.settings_rounded),
              ),
            ],
          ),
          body: PageView(
            children: const [
              HomePortion(),
              SettingsPortion(),
            ],
          ),
        );
      }
    
      int _pageIndex = 0;
      PageController _controller = PageController();
    }
    
    Login or Signup to reply.
  2. in your code

    class MainScreen extends StatefulWidget
    {
      static const String mainScreenId = "mainScreenId";
    
      @override
      _MainScreenState createState() => _MainScreenState();
    }
    
    class _MainScreenState extends State<MainScreen> with SingleTickerProviderStateMixin
    {
      TabController? tabController;
    
      int selectedIndex = 0;
      bool online = false;
    
      void onItemClicked(int index)
      {
        setState(()
        {
          selectedIndex = index;
          tabController!.index = selectedIndex;
        });
      }
    
      @override
      void initState() {
        // TODO: implement initState
        super.initState();
    
        tabController = TabController(length: 4, vsync: this);
      }
    
      @override
      void dispose() {
        // TODO: implement dispose
        super.dispose();
        tabController!.dispose();
      }
    
      @override
      Widget build(BuildContext context) {
        return Scaffold
        (
          appbar: AppBar(
            actions:[
              Text("online "),
              Switch(
               onChanged:(value){setState((){
                      online = value
                       });}   ,
               value: online       
             )]
          ),
          body: TabBarView(
            physics: NeverScrollableScrollPhysics(),
            controller: tabController,
            children:
            [
              HomeScreen(),
              EarningsScreen(),
              ZonesScreen(),
              ProfileScreen(),
            ],
            //index: selectedIndex,
          ),
          bottomNavigationBar: BottomNavigationBar(
            items:
            [
              BottomNavigationBarItem(
                icon: Icon(
                    Icons.home,
                  ),
                label: 'Home',
              ),
              BottomNavigationBarItem(
                icon: Icon(
                    Icons.credit_card,
                  ),
                label: 'Earnings',
              ),
              BottomNavigationBarItem(
                icon: Icon(
                    Icons.settings_input_antenna_rounded,
                  ),
                label: 'Zones',
              ),
              BottomNavigationBarItem(
                icon: Icon(
                    Icons.person,
                  ),
                label: 'Account',
              ),
            ],
            unselectedItemColor: Colors.black54,
            selectedItemColor: Colors.blue,
            type: BottomNavigationBarType.fixed,
            selectedLabelStyle: TextStyle(
              fontSize: 12.0
            ),
            showUnselectedLabels: true,
            currentIndex: selectedIndex,
            onTap: onItemClicked,
          ),
        );
      }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search