AQRC
AQRC

Reputation: 323

Flutter: how to keep widget with Google Map unchanged?

I am using Google Maps for Flutter widget. In my app map is displayed via one of the tabs of BottomNavigationBar.

And I have the following problem:

  1. user is on Map's tab
  2. user changes tab (by tapping on another one)
  3. [PROBLEM] when user returns on Map's tab map redraws.

I would like to keep map as it is when user leaves Map's tab, so he can continue to work with it when he returns to it later on.

Tried to:

(I admit that I could have done something wrong)

Code of last attempt:

class MapScreen extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => MapScreenState();
}

class MapScreenState extends State<MapScreen> with AutomaticKeepAliveClientMixin {
  GoogleMapController mapController;

  @override
  bool get wantKeepAlive => true;

  @override
  Widget build(BuildContext context) {
    super.build(context);
    return Scaffold(
        appBar: AppBar(
          title: const Text("Map"),
        ),
        body: GoogleMap(
          onMapCreated: _onMapCreated,
        )
    );
  }

  void _onMapCreated(GoogleMapController controller) {
      mapController = controller;
      updateKeepAlive();
  }
}

So, I just need a way to either keep MapScreen alive and unchanged, or to store its state somehow and restore it when user returns to MapScreen. Or something else which will solve the problem.

Upvotes: 22

Views: 5323

Answers (4)

Iyyappan
Iyyappan

Reputation: 26

AutomaticKeepAliveClientMixin

To

AutomaticKeepAliveClientMixin<MapScreenState>

Upvotes: -1

Rinaldi Segecin
Rinaldi Segecin

Reputation: 517

I was just having this same problem and the mixin solved it. I think you've just missed enter the type of mixin at the end of its declaration.

class MapScreenState extends State<MapScreen> with AutomaticKeepAliveClientMixin<MapScreenState>

see this thread if anything.

Upvotes: 2

AaronJ
AaronJ

Reputation: 714

Use IndexedStack

For example:

Class _ExamplePageState extends State<ExamplePage> {
  int _bottomNavIndex = 0;

  final List<Widget> _children = [
    WidgetOne(),
    WidgetTwo(),
    GoogleMap(),
  ]

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: IndexedStack(
        index: _bottomNavIndex,
        children: _children,
      ),
      bottomNavigationBar: BottomNavigationBar(
        currentIndex: _bottomNavIndex,
        onTap: (index) {
          if (_bottomNavIndex == index) return;
          setState(() {
            _bottomNavIndex = index;
          });
        }
        items: [ ... ]
      ),
    );
  }
}

Upvotes: 8

diegoveloper
diegoveloper

Reputation: 103401

Widget always rebuild after you change from page to page, so, try this , use a variable for GoogleMap and reuse if it's different from null.

    GoogleMap _map;

     @override
    Widget build(BuildContext context) {
      if (_map == null){
        _map =  GoogleMap(
            onMapCreated: _onMapCreated,
          );
      }
      return Scaffold(
          appBar: AppBar(
            title: const Text("Map"),
          ),
          body:_map,
      );
    }

Upvotes: 3

Related Questions