cofounderella/lib/components/location_selector.dart

203 lines
6.5 KiB
Dart
Raw Normal View History

import 'package:flutter/material.dart';
import 'package:geocoding/geocoding.dart';
import 'package:geolocator/geolocator.dart';
import '../models/location.dart';
class LocationSelector extends StatefulWidget {
2024-05-09 21:55:17 +02:00
final Function(MyLocation) onLocationChanged; // Callback function
const LocationSelector({super.key, required this.onLocationChanged});
@override
LocationSelectorState createState() => LocationSelectorState();
}
class LocationSelectorState extends State<LocationSelector> {
final TextEditingController _locationController = TextEditingController();
String _street = '';
String _country = '';
String? _administrativeArea; // DE: Bundesland
String _city = '';
String? _subLocality; // DE: Stadtteil
String? _postalCode;
double? _latitude;
double? _longitude;
String? errorText;
@override
Widget build(BuildContext context) {
2024-06-12 00:39:29 +02:00
return SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
TextField(
// onSubmitted: (loc) => {_searchLocation2(loc)},
controller: _locationController,
decoration: InputDecoration(
labelText: 'Enter location',
suffixIcon: IconButton(
icon: const Icon(Icons.search),
onPressed: _searchLocation,
),
),
2024-05-09 21:55:17 +02:00
),
2024-06-12 00:39:29 +02:00
Text(
errorText != null ? '$errorText' : '',
style: const TextStyle(color: Colors.red),
),
const SizedBox(height: 20),
ElevatedButton(
onPressed: _getCurrentLocation,
child: const Text('Use Current Position'),
),
const SizedBox(height: 20),
Text('Country: $_country'),
Text('City: $_city'),
Text('Postal Code: $_postalCode'),
Text('Street: $_street'),
Text('Administrative Area: $_administrativeArea'),
Text('Latitude: $_latitude'),
Text('Longitude: $_longitude'),
],
),
2024-05-09 21:55:17 +02:00
);
}
void _searchLocation() async {
2024-05-10 00:21:23 +02:00
String locationQuery = _locationController.text.trim();
2024-05-10 00:21:23 +02:00
if (locationQuery.isEmpty) {
_resetLocationData('Specify an address for the search');
return;
}
try {
List<Location> locations = await locationFromAddress(locationQuery);
if (locations.isNotEmpty) {
// Take first match
Location firstLocation = locations.first;
// Extract country and city information
List<Placemark> placeMarks = await placemarkFromCoordinates(
firstLocation.latitude, firstLocation.longitude);
if (placeMarks.isNotEmpty) {
Placemark placeMark = placeMarks.first;
setState(() {
_latitude = firstLocation.latitude;
_longitude = firstLocation.longitude;
_street = '${placeMark.street}';
_country = placeMark.country!;
_city = placeMark.locality!;
_subLocality = placeMark.subLocality;
_postalCode = placeMark.postalCode;
_administrativeArea = placeMark.administrativeArea;
errorText = null;
});
2024-05-09 21:55:17 +02:00
// location is found, trigger callback
triggerCallback();
} else {
setState(() {
// should placeMarks be empty return latitude and longitude anyway
_latitude = firstLocation.latitude;
_longitude = firstLocation.longitude;
errorText = null;
});
}
} else {
2024-05-10 00:21:23 +02:00
_resetLocationData('Location $locationQuery not found');
}
} catch (e) {
2024-05-10 00:21:23 +02:00
_resetLocationData('Error searching location $locationQuery: $e');
}
}
void triggerCallback(){
widget.onLocationChanged(MyLocation(
street: _street,
country: _country,
administrativeArea: _administrativeArea,
locality: _city,
subLocality: _subLocality,
postalCode: _postalCode,
latitude: _latitude,
longitude: _longitude,
));
}
2024-05-10 00:21:23 +02:00
/// Resets the location data and calls setState()
void _resetLocationData(String errorMessage) {
setState(() {
errorText = errorMessage;
_street = '';
_country = '';
_city = '';
_subLocality = null;
_postalCode = null;
_administrativeArea = null;
_latitude = null;
_longitude = null;
});
}
/// Determine users position using geolocator package
void _getCurrentLocation() async {
bool serviceEnabled;
LocationPermission permission;
try {
// Test if location services are enabled.
serviceEnabled = await Geolocator.isLocationServiceEnabled();
if (!serviceEnabled) {
// Location services are not enabled don't continue
// accessing the position and request users of the
// App to enable the location services.
return Future.error('Location services are disabled.');
}
permission = await Geolocator.checkPermission();
if (permission == LocationPermission.denied) {
permission = await Geolocator.requestPermission();
if (permission == LocationPermission.denied) {
// Permissions are denied, next time you could try
// requesting permissions again (this is also where
// Android's shouldShowRequestPermissionRationale
// returned true. According to Android guidelines
// your App should show an explanatory UI now.
return Future.error('Location permissions are denied');
}
}
if (permission == LocationPermission.deniedForever) {
// Permissions are denied forever, handle appropriately.
return Future.error(
'Location permissions are permanently denied, we cannot request permissions.');
}
} catch (e) {
2024-06-07 02:18:20 +02:00
debugPrint('Error getting location permission: $e');
}
try {
// When we reach here, permissions are granted and we can
// continue accessing the position of the device.
Position position = await Geolocator.getCurrentPosition(
desiredAccuracy: LocationAccuracy.high);
List<Placemark> placeMarks =
await placemarkFromCoordinates(position.latitude, position.longitude);
if (placeMarks.isNotEmpty) {
Placemark placeMark = placeMarks.first;
setState(() {
_street = placeMark.street!;
_country = placeMark.country!;
_city = placeMark.locality!;
_latitude = position.latitude;
_longitude = position.longitude;
});
triggerCallback();
}
} catch (e) {
2024-06-07 02:18:20 +02:00
debugPrint('Error getting current location: $e');
}
}
}