tlserver / flutter_map_location_marker

A flutter map plugin for displaying device current location.
https://pub.dev/packages/flutter_map_location_marker
BSD 3-Clause "New" or "Revised" License
98 stars 83 forks source link

LocationMarker not showing after location permissions change #21

Closed RedHappyLlama closed 2 years ago

RedHappyLlama commented 2 years ago

Hi,

I have a very similar set up to one of the example apps: https://github.com/tlserver/flutter_map_location_marker/blob/master/example/lib/page/center_fab_example.dart

However, if the map page is loaded when location permissions are denied, tapping the FAB encourages the user to change the user permissions in the settings.

The issue is; if the user then grants location permissions, once the location is retrieved, the location marker doesn't show and the screen isn't centred on location.

if (phoneLocation.error) { APIResponse<bool> _locationServiceActive = await locationService.checkLocationService(); if (_locationServiceActive.data) { phoneLocation = await locationService.getCurrentLocation(); setState(() => _centerOnLocationUpdate = CenterOnLocationUpdate.always); _centerCurrentLocationStreamController.add(17);

Thanks!

RedHappyLlama commented 2 years ago

Used this logic.

https://github.com/tlserver/flutter_map_location_marker/issues/11

RedHappyLlama commented 2 years ago

Still has a performance issue due to stream listener.

======== Exception caught by widgets library ======================================================= The following StateError was thrown building RawGestureDetector(state: RawGestureDetectorState#b3f04(gestures: [scale, vertical drag, horizontal drag])): Bad state: Stream has already been listened to.

The relevant error-causing widget was: RawGestureDetector RawGestureDetector:file:///Users/benfloyd/Developer/flutter/.pub-cache/hosted/pub.dartlang.org/flutter_map-0.14.0/lib/src/map/flutter_map_state.dart:88:11 When the exception was thrown, this was the stack:

3 _LocationMarkerLayerState.initState (package:flutter_map_location_marker/flutter_map_location_marker.dart:188:52)

tlserver commented 2 years ago

It works for me in this settings. The location marker show up and the map is centered to the marker.

import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:flutter_map_location_marker/flutter_map_location_marker.dart';
import 'package:latlong2/latlong.dart';

class CenterFabExample extends StatefulWidget {
  @override
  _CenterFabExampleState createState() => _CenterFabExampleState();
}

class _CenterFabExampleState extends State<CenterFabExample> {
  late CenterOnLocationUpdate _centerOnLocationUpdate;
  late StreamController<double?> _centerCurrentLocationStreamController;

  @override
  void initState() {
    super.initState();
    _centerOnLocationUpdate = CenterOnLocationUpdate.always;
    _centerCurrentLocationStreamController = StreamController<double?>();
  }

  @override
  void dispose() {
    _centerCurrentLocationStreamController.close();
    super.dispose();
  }

  bool _isShowLocMarker = false;

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: [
        FlutterMap(
          options: MapOptions(
            center: LatLng(0, 0),
            zoom: 1,
            maxZoom: 19,
            // Stop centering the location marker on the map if user interacted with the map.
            onPositionChanged: (MapPosition position, bool hasGesture) {
              if (hasGesture) {
                setState(
                  () => _centerOnLocationUpdate = CenterOnLocationUpdate.never,
                );
              }
            },
          ),
          children: [
            TileLayerWidget(
              options: TileLayerOptions(
                urlTemplate:
                    'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
                subdomains: ['a', 'b', 'c'],
                maxZoom: 19,
              ),
            ),
            if (_isShowLocMarker)
              LocationMarkerLayerWidget(
                plugin: LocationMarkerPlugin(
                  centerCurrentLocationStream:
                      _centerCurrentLocationStreamController.stream,
                  centerOnLocationUpdate: _centerOnLocationUpdate,
                ),
              ),
          ],
        ),
        Positioned(
          right: 20,
          bottom: 80,
          child: Column(
            children: [
              FloatingActionButton(
                heroTag: null,
                onPressed: () => setState(() {
                  _isShowLocMarker = false;
                  _centerCurrentLocationStreamController.close();
                }),
                child: const Icon(
                  Icons.gps_off,
                  color: Colors.white,
                ),
              ),
              const SizedBox(height: 20),
              FloatingActionButton(
                heroTag: null,
                onPressed: () {
                  // Automatically center the location marker on the map when location updated until user interact with the map.
                  setState(() {
                    if (!_isShowLocMarker) {
                      _centerCurrentLocationStreamController =
                          StreamController<double>();
                    }
                    _centerOnLocationUpdate = CenterOnLocationUpdate.once;
                    _isShowLocMarker = true;
                  });
                  // Center the location marker on the map and zoom the map to level 18.
                  _centerCurrentLocationStreamController.add(18);
                },
                child: const Icon(
                  Icons.my_location,
                  color: Colors.white,
                ),
              ),
            ],
          ),
        ),
      ],
    );
  }
}

https://user-images.githubusercontent.com/8895426/152629866-e056ae4d-033a-4b69-9715-b8ba2a7b84cb.mp4

RedHappyLlama commented 2 years ago

Hi,

Thanks! I wasn't closing the old stream and opening a new one.