// @dart=2.9
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'dart:convert';
import 'package:geolocator/geolocator.dart';
import 'package:intl/intl.dart';
import 'package:geocoding/geocoding.dart';
class Weather extends StatefulWidget {
@override
_WeatherState createState() => _WeatherState();
}
class _WeatherState extends State<Weather> {
int temperature;
var minTemperatureForecast = new List(7);
var maxTemperatureForecast = new List(7);
String location = 'San Francisco';
int woeid = 2487956;
String weather = 'clear';
String abbreviation = '';
var abbreviationForecast = new List(7);
String errorMessage = '';
final Geolocator geolocator = Geolocator()..forceAndroidLocationManager;
Position _currentPosition;
String _currentAddress;
String searchApiUrl =
'https://www.metaweather.com/api/location/search/?query=';
String locationApiUrl = 'https://www.metaweather.com/api/location/';
get geocoding => null;
initState() {
super.initState();
fetchLocation();
fetchLocationDay();
}
void fetchSearch(String input) async {
try {
var searchResult = await http.get(Uri.parse(searchApiUrl + input));
var result = json.decode(searchResult.body)[0];
setState(() {
location = result["title"];
woeid = result["woeid"];
errorMessage = '';
});
} catch (error) {
setState(() {
errorMessage =
"Sorry, we don't have data about this city. Try another one.";
});
}
}
void fetchLocation() async {
var locationResult = await http.get(Uri.parse(locationApiUrl + woeid.toString()));
var result = json.decode(locationResult.body);
var consolidated_weather = result["consolidated_weather"];
var data = consolidated_weather[0];
setState(() {
temperature = data["the_temp"].round();
weather = data["weather_state_name"].replaceAll(' ', '').toLowerCase();
abbreviation = data["weather_state_abbr"];
});
}
void fetchLocationDay() async {
var today = new DateTime.now();
for (var i = 0; i < 7; i++) {
var locationDayResult = await http.get(Uri.parse(locationApiUrl +
woeid.toString() +
'/' +
new DateFormat('y/M/d')
.format(today.add(new Duration(days: i + 1)))
.toString()));
var result = json.decode(locationDayResult.body);
var data = result[0];
setState(() {
minTemperatureForecast[i] = data["min_temp"].round();
maxTemperatureForecast[i] = data["max_temp"].round();
abbreviationForecast[i] = data["weather_state_abbr"];
});
}
}
void onTextFieldSubmitted(String input) async {
await fetchSearch(input);
await fetchLocation();
await fetchLocationDay();
}
_getCurrentLocation() {
Geolocator
.getCurrentPosition(desiredAccuracy: LocationAccuracy.best,forceAndroidLocationManager: true)
.then((Position position) {
setState(() {
_currentPosition = position;
});
_getAddressFromLatLng();
}).catchError((e) {
print(e);
});
}
_getAddressFromLatLng() async {
try {
List<Placemark> p = await geocoding.placemarkFromCoordinates(
_currentPosition.latitude, _currentPosition.longitude);
Placemark place = p[0];
setState(() {
_currentAddress =
"${place.locality}, ${place.postalCode}, ${place.country}";
});
onTextFieldSubmitted(place.locality);
print(place.locality);
} catch (e) {
print(e);
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Container(
decoration: BoxDecoration(
image: DecorationImage(
image: AssetImage('images/$weather.png'),
fit: BoxFit.cover,
colorFilter: new ColorFilter.mode(
Colors.black.withOpacity(0.6), BlendMode.dstATop),
),
),
child: temperature == null
? Center(child: CircularProgressIndicator())
: Scaffold(
appBar: AppBar(
actions: <Widget>[
Padding(
padding: EdgeInsets.only(right: 300.0),
child: IconButton(
onPressed: () {
Navigator.pop(context);
},
icon: Icon(Icons.arrow_back, size: 40.0, color: Colors.black,
),
),),
Padding(
padding: const EdgeInsets.only(right: 5.0),
child: GestureDetector(
onTap: () {
_getCurrentLocation();
},
child: Icon(Icons.location_city, size: 36.0),
),
)
],
backgroundColor: Colors.transparent,
elevation: 0.0,
),
resizeToAvoidBottomInset: false,
backgroundColor: Colors.transparent,
body: Column(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
Column(
children: <Widget>[
Center(
child: Image.network(
'https://www.metaweather.com/static/img/weather/png/' +
abbreviation +
'.png',
width: 100,
),
),
Center(
child: Text(
temperature.toString() + ' °C',
style: TextStyle(
color: Colors.white, fontSize: 60.0),
),
),
Center(
child: Text(
location,
style: TextStyle(
color: Colors.white, fontSize: 40.0),
),
),
],
),
SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: Row(
children: <Widget>[
// ignore: sdk_version_ui_as_code
for (var i = 0; i < 7; i++)
forecastElement(
i + 1,
abbreviationForecast[i],
minTemperatureForecast[i],
maxTemperatureForecast[i]),
],
),
),
Column(
children: <Widget>[
Container(
width: 300,
child: TextField(
onSubmitted: (String input) {
onTextFieldSubmitted(input);
},
style:
TextStyle(color: Colors.white, fontSize: 25),
decoration: InputDecoration(
hintText: 'Search another location...',
hintStyle: TextStyle(
color: Colors.white, fontSize: 18.0),
prefixIcon:
Icon(Icons.search, color: Colors.white),
),
),
),
Padding(
padding:
const EdgeInsets.only(right: 32.0, left: 32.0),
child: Text(errorMessage,
textAlign: TextAlign.center,
style: TextStyle(
color: Colors.redAccent,
fontSize:
Platform.isAndroid ? 15.0 : 20.0)),
)
],
),
],
),
)),
);
}
}
/// Contains detailed placemark information.
class Placemark {
/// Constructs an instance with the given values for testing. [Placemark]
/// instances constructed this way won't actually reflect any real information
/// from the platform, just whatever was passed in at construction time.
Placemark(
{this.name,
this.isoCountryCode,
this.country,
this.postalCode,
this.administrativeArea,
this.subAdministrativeArea,
this.locality,
this.subLocality,
this.thoroughfare,
this.subThoroughfare,
this.position});
Placemark._(
{this.name,
this.isoCountryCode,
this.country,
this.postalCode,
this.administrativeArea,
this.subAdministrativeArea,
this.locality,
this.subLocality,
this.thoroughfare,
this.subThoroughfare,
this.position});
/// The name of the placemark.
final String name;
/// The abbreviated country name, according to the two letter (alpha-2) [ISO standard](https://www.iso.org/iso-3166-country-codes.html).
final String isoCountryCode;
/// The name of the country associated with the placemark.
final String country;
/// The postal code associated with the placemark.
final String postalCode;
/// The name of the state or province associated with the placemark.
final String administrativeArea;
/// Additional administrative area information for the placemark.
final String subAdministrativeArea;
/// The name of the city associated with the placemark.
final String locality;
/// Additional city-level information for the placemark.
final String subLocality;
/// The street address associated with the placemark.
final String thoroughfare;
/// Additional street address information for the placemark.
final String subThoroughfare;
/// The geocoordinates associated with the placemark.
final Position position;
@override
bool operator ==(o) =>
o is Placemark &&
o.administrativeArea == administrativeArea &&
o.country == country &&
o.isoCountryCode == isoCountryCode &&
o.locality == locality &&
o.name == name &&
o.position == position &&
o.postalCode == postalCode &&
o.subAdministrativeArea == subAdministrativeArea &&
o.subLocality == subLocality &&
o.subThoroughfare == subThoroughfare &&
o.thoroughfare == thoroughfare;
@override
int get hashCode =>
administrativeArea.hashCode ^
country.hashCode ^
isoCountryCode.hashCode ^
locality.hashCode ^
name.hashCode ^
position.hashCode ^
postalCode.hashCode ^
subAdministrativeArea.hashCode ^
subLocality.hashCode ^
subThoroughfare.hashCode ^
thoroughfare.hashCode;
/// Converts a list of [Map] instances to a list of [Placemark] instances.
static List<Placemark> fromMaps(dynamic message) {
if (message == null) {
throw ArgumentError('The parameter \'message\' should not be null.');
}
final List<Placemark> list = message.map<Placemark>(fromMap).toList();
return list;
}
/// Converts the supplied [Map] to an instance of the [Placemark] class.
static Placemark fromMap(dynamic message) {
if (message == null) {
throw ArgumentError('The parameter \'message\' should not be null.');
}
final Map<dynamic, dynamic> placemarkMap = message;
return Placemark._(
name: placemarkMap['name'] ?? '',
isoCountryCode: placemarkMap['isoCountryCode'] ?? '',
country: placemarkMap['country'] ?? '',
postalCode: placemarkMap['postalCode'] ?? '',
administrativeArea: placemarkMap['administrativeArea'] ?? '',
subAdministrativeArea: placemarkMap['subAdministrativeArea'] ?? '',
locality: placemarkMap['locality'] ?? '',
subLocality: placemarkMap['subLocality'] ?? '',
thoroughfare: placemarkMap['thoroughfare'] ?? '',
subThoroughfare: placemarkMap['subThoroughfare'] ?? '',
position: placemarkMap['position'] != null
? Position.fromMap(placemarkMap['position'])
: null,
);
}
/// Converts the [Placemark] instance into a [Map] instance that can be serialized to JSON.
Map<String, dynamic> toJson() => {
'name': name,
'isoCountryCode': isoCountryCode,
'country': country,
'postalCode': postalCode,
'administrativeArea': administrativeArea,
'subAdministrativeArea': subAdministrativeArea,
'locality': locality,
'subLocality': subLocality,
'thoroughfare': thoroughfare,
'subThoroughfare': subThoroughfare,
'position': position.toJson()
};
}
Widget forecastElement(
daysFromNow, abbreviation, minTemperature, maxTemperature) {
var now = new DateTime.now();
var oneDayFromNow = now.add(new Duration(days: daysFromNow));
return Padding(
padding: const EdgeInsets.only(left: 16.0),
child: Container(
decoration: BoxDecoration(
color: Color.fromRGBO(205, 212, 228, 0.2),
borderRadius: BorderRadius.circular(10),
),
child: Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: <Widget>[
Text(
new DateFormat.E().format(oneDayFromNow),
style: TextStyle(color: Colors.white, fontSize: 25),
),
Text(
new DateFormat.MMMd().format(oneDayFromNow),
style: TextStyle(color: Colors.white, fontSize: 20),
),
Padding(
padding: const EdgeInsets.only(top: 16.0, bottom: 16.0),
child: Image.network(
'https://www.metaweather.com/static/img/weather/png/' +
abbreviation +
'.png',
width: 50,
),
),
Text(
'High: ' + maxTemperature.toString() + ' °C',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
Text(
'Low: ' + minTemperature.toString() + ' °C',
style: TextStyle(color: Colors.white, fontSize: 20.0),
),
],
),
),
),
);
}
我正在尝试使用地标在我的 flutter 应用程序中获取用户位置。我已经导入了运行应用程序所需的所有必要依赖项,但我仍然在地理定位器地标中收到错误消息。我不知道该怎么办。
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:geolocator/geolocator.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:ft06/requests/google_maps_requests.dart';
class AppState with ChangeNotifier {
static LatLng _initialPosition;
LatLng _lastPosition = _initialPosition;
bool locationServiceActive = true;
final Set<Marker> _markers = {};
final Set<Polyline> _polyLines = {};
GoogleMapController _mapController;
GoogleMapsServices _googleMapsServices = GoogleMapsServices();
TextEditingController locationController = TextEditingController();
TextEditingController destinationController = TextEditingController();
LatLng get initialPosition => _initialPosition;
LatLng get lastPosition => _lastPosition;
GoogleMapsServices get googleMapsServices => _googleMapsServices;
GoogleMapController get mapController => _mapController;
Set<Marker> get markers => _markers;
Set<Polyline> get polyLines => _polyLines;
AppState() {
_getUserLocation();
_loadingInitialPosition();
}
// ! TO GET THE USERS LOCATION
void _getUserLocation() async {
print("GET USER METHOD RUNNING =========");
Position position = await Geolocator()
.getCurrentPosition(desiredAccuracy:LocationAccuracy.high);
List<Placemark> placemark = await Geolocator()
.placemarkFromCoordinates(position.latitude, position.longitude);
_initialPosition = LatLng(position.latitude, position.longitude);
print("the latitude is: ${position.longitude} and th longitude is: ${position.longitude} ");
print("initial position is : ${_initialPosition.toString()}");
locationController.text = placemark[0].name;
notifyListeners();
}
终端上的实际错误输出在这里: