mimic google behavior with location icon button
This commit is contained in:
parent
507b321311
commit
c00d2fac05
8
lib/extensions/positionLatLngExtension.dart
Normal file
8
lib/extensions/positionLatLngExtension.dart
Normal file
@ -0,0 +1,8 @@
|
||||
import 'package:geolocator/geolocator.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
extension LatLngPositionExtension on Position {
|
||||
LatLng latlng() {
|
||||
return LatLng(latitude, longitude);
|
||||
}
|
||||
}
|
@ -4,13 +4,13 @@ import 'package:geolocator/geolocator.dart';
|
||||
import 'package:latlong2/latlong.dart';
|
||||
|
||||
class MapState extends ChangeNotifier {
|
||||
bool _isCurrentlyLoading = false;
|
||||
bool _isLocationLive = false;
|
||||
LatLng? _currentLocation;
|
||||
LatLng? _activeMarker;
|
||||
final MapController _mapController = MapController();
|
||||
final Geolocator _geolocator = Geolocator();
|
||||
|
||||
bool get isCurrentlyLoading => _isCurrentlyLoading;
|
||||
bool get isLocationLive => _isLocationLive;
|
||||
LatLng? get getCurrentLocation => _currentLocation;
|
||||
LatLng? get getActiveMarker => _activeMarker;
|
||||
MapController get getMapController => _mapController;
|
||||
@ -18,16 +18,21 @@ class MapState extends ChangeNotifier {
|
||||
|
||||
void setCurrentLocation(LatLng? currentLocation) {
|
||||
_currentLocation = currentLocation;
|
||||
if (currentLocation != null) _mapController.move(currentLocation, 16);
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setActiveMarker(LatLng? marker) {
|
||||
_activeMarker = marker;
|
||||
if (marker != null) {
|
||||
_isLocationLive = false;
|
||||
_mapController.move(marker, 16);
|
||||
}
|
||||
notifyListeners();
|
||||
}
|
||||
|
||||
void setLoading(bool loading) {
|
||||
_isCurrentlyLoading = loading;
|
||||
void setLocationLive(bool live) {
|
||||
_isLocationLive = live;
|
||||
notifyListeners();
|
||||
}
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
import 'package:app/extensions/obtainProviderExtension.dart';
|
||||
import 'package:app/extensions/positionLatLngExtension.dart';
|
||||
import 'package:app/state/mapState.dart';
|
||||
import 'package:app/state/timeStatusState.dart';
|
||||
import 'package:app/util/watchState.dart';
|
||||
@ -19,41 +20,70 @@ class HomeView extends StatefulWidget {
|
||||
|
||||
class _HomePageState extends State<HomeView> {
|
||||
bool locationEnabled = false;
|
||||
|
||||
Future<LatLng?> getLatLng() async {
|
||||
LocationPermission permission = await Geolocator.checkPermission();
|
||||
if (permission == LocationPermission.denied) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
setState(() {
|
||||
locationEnabled = true;
|
||||
});
|
||||
|
||||
Position? position;
|
||||
try {
|
||||
position = await Geolocator.getCurrentPosition();
|
||||
} catch (e) {
|
||||
position = await Geolocator.getLastKnownPosition();
|
||||
}
|
||||
|
||||
if (position != null) {
|
||||
return LatLng(position.latitude, position.longitude);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
bool locationLoading = false;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
|
||||
Geolocator.checkPermission().then((permission) => setState(() {
|
||||
locationEnabled = permission != LocationPermission.denied && permission != LocationPermission.deniedForever;
|
||||
}));
|
||||
Geolocator.getServiceStatusStream().listen((status) {
|
||||
setState(() {
|
||||
locationEnabled = status == ServiceStatus.enabled;
|
||||
});
|
||||
});
|
||||
|
||||
requestLiveLocation(context.obtainState<MapState>(), false, true, true);
|
||||
}
|
||||
|
||||
Future<void> requestLiveLocation(MapState mapState, bool ask, bool orLast, bool loadingIndicator) async {
|
||||
Position? position;
|
||||
LocationPermission permission = await Geolocator.checkPermission();
|
||||
|
||||
if (loadingIndicator && permission != LocationPermission.deniedForever) {
|
||||
setState(() {
|
||||
locationLoading = true;
|
||||
});
|
||||
}
|
||||
|
||||
if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
|
||||
if (ask && permission != LocationPermission.deniedForever) {
|
||||
permission = await Geolocator.requestPermission();
|
||||
}
|
||||
if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
|
||||
if (orLast) position = await Geolocator.getLastKnownPosition();
|
||||
}
|
||||
}
|
||||
|
||||
if (permission == LocationPermission.denied || permission == LocationPermission.deniedForever) {
|
||||
if (position != null) {
|
||||
setState(() => locationEnabled = true);
|
||||
mapState.setCurrentLocation(position.latlng());
|
||||
}
|
||||
setState(() => locationLoading = false);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
position = await Geolocator.getCurrentPosition();
|
||||
setState(() {
|
||||
locationEnabled = true;
|
||||
});
|
||||
mapState.setLocationLive(true);
|
||||
mapState.setCurrentLocation(position.latlng());
|
||||
Geolocator.getServiceStatusStream().first.then((_) => setState(() {
|
||||
mapState.setLocationLive(false);
|
||||
}));
|
||||
} catch (_) {
|
||||
if (orLast) {
|
||||
position = await Geolocator.getLastKnownPosition();
|
||||
if (position != null) {
|
||||
setState(() => locationEnabled = true);
|
||||
mapState.setCurrentLocation(position.latlng());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
setState(() => locationLoading = false);
|
||||
}
|
||||
|
||||
@override
|
||||
@ -72,9 +102,6 @@ class _HomePageState extends State<HomeView> {
|
||||
delegate: LocationSearchDelegate(),
|
||||
);
|
||||
mapState.setActiveMarker(latLng);
|
||||
if (latLng != null) {
|
||||
mapState.getMapController.move(latLng, 16);
|
||||
}
|
||||
},
|
||||
),
|
||||
IconButton(
|
||||
@ -90,26 +117,15 @@ class _HomePageState extends State<HomeView> {
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: WatchState<MapState>((context, state) {
|
||||
if(locationEnabled) {
|
||||
if(state.isCurrentlyLoading) {
|
||||
return const Padding(padding: EdgeInsets.all(15), child: CircularProgressIndicator(strokeWidth: 3));
|
||||
} else {
|
||||
return const Icon(Icons.my_location);
|
||||
}
|
||||
if (locationLoading) {
|
||||
return const Padding(padding: EdgeInsets.all(15), child: CircularProgressIndicator(strokeWidth: 3));
|
||||
}
|
||||
if (locationEnabled) {
|
||||
return Icon(state.isLocationLive ? Icons.my_location : Icons.location_searching);
|
||||
}
|
||||
|
||||
return const Icon(Icons.location_disabled);
|
||||
}),
|
||||
onPressed: () async {
|
||||
MapState mapState = context.obtainState<MapState>();
|
||||
mapState.setLoading(true);
|
||||
LatLng? latLng = await getLatLng();
|
||||
if (latLng != null) {
|
||||
mapState.setCurrentLocation(latLng);
|
||||
mapState.getMapController.move(latLng, 16);
|
||||
}
|
||||
mapState.setLoading(false);
|
||||
},
|
||||
onPressed: () => requestLiveLocation(context.obtainState<MapState>(), true, false, true),
|
||||
),
|
||||
body: Column(
|
||||
children: [
|
||||
|
@ -1,7 +1,6 @@
|
||||
import 'package:app/extensions/obtainProviderExtension.dart';
|
||||
import 'package:app/state/mapState.dart';
|
||||
import 'package:app/util/watchState.dart';
|
||||
import 'package:flutter/cupertino.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_map/flutter_map.dart';
|
||||
import 'package:http/http.dart';
|
||||
@ -20,10 +19,13 @@ class _MapViewState extends State<MapView> {
|
||||
Widget build(BuildContext context) {
|
||||
return FlutterMap(
|
||||
mapController: context.obtainState<MapState>().getMapController,
|
||||
options: const MapOptions(
|
||||
initialCenter: LatLng(50.354, 7.5845),
|
||||
options: MapOptions(
|
||||
onPositionChanged: (position, hasGesture) => {
|
||||
if (hasGesture) context.obtainState<MapState>().setLocationLive(false)
|
||||
},
|
||||
initialCenter: const LatLng(50.354, 7.5845),
|
||||
initialZoom: 16,
|
||||
interactionOptions: InteractionOptions(
|
||||
interactionOptions: const InteractionOptions(
|
||||
flags: InteractiveFlag.all & ~InteractiveFlag.rotate
|
||||
)
|
||||
),
|
||||
|
Reference in New Issue
Block a user