Reputation: 180
I'm using Flutter for the first time in order to build a mobile application and I found no way to implement autocomplete google places in a textEdit component. I aim to obtain a kind of list view while the user is typing the location, as we can do in Android/iOS native implementation and react/ionic.
What I did obtain is a TextEdit component that searches possible locations and take the first one at the end. Here a snippet of my code
class HomeFragmentState extends State<HomeFragment>{
GoogleMapController mapController;
String searchAddr;
List<Marker> markersList = [];
Marker finalMarker;
LatLng _center = LatLng(45.4654219,9.1859243); // default location
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
GoogleMap(
onMapCreated: onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 11.0,
),
markers: Set.from(markersList),
),
Positioned(
top: 10.0,
right: 15.0,
left: 15.0,
child: Container(
height: 50.0,
width: double.infinity,
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(10.0),
color: Colors.white
),
child: Column(
children: <Widget>[
TextField(
decoration: InputDecoration(
hintText: 'Enter the place',
border: InputBorder.none,
contentPadding: EdgeInsets.only(left: 15.0,top:15.0),
suffixIcon: IconButton(
icon: Icon(Icons.search),
onPressed: searchAndNavigate,
iconSize: 30.0,
)
),
onChanged: (val) {
setState(() {
searchAddr = val;
});
},
onEditingComplete: searchAndNavigate,
),
],
)
),
),
],
),
);
}
void searchAndNavigate(){
Geolocator().placemarkFromAddress(searchAddr).then((result) => {navigateTo(result:result)});
}
navigateTo({result, init: false}){
var zoom = 11.0;
var target;
if(init){
zoom = 12.0; //difference between searching and initializing
target = LatLng(result.latitude, result.longitude);
} else {
target = LatLng(result[0].position.latitude,result[0].position.longitude);
}
mapController.animateCamera(CameraUpdate.newCameraPosition(CameraPosition(
target:target,
zoom: zoom
)));
}
void onMapCreated(controller){
setState(() {
mapController = controller;
Geolocator().getCurrentPosition(desiredAccuracy: LocationAccuracy.high).then((position) => {
navigateTo(result: position,init: true)
});
});
}
}
As we can see from Geolocator we can retrieve some location based on the address we're typing (hence we can take the results from there) but I didn't find a smart way to implement the part of textedit suggestions
Upvotes: 4
Views: 26986
Reputation: 67
Google places autocomplete widgets for flutter.
Future<void> _handlePressButton() async {
// show input autocomplete with selected mode
// then get the Prediction selected
Prediction? prediction = await PlacesAutocomplete.show(
context: context,
apiKey: kGoogleApiKey,
onError: onError,
mode: Mode.fullscreen,
// Mode.overlay
//language: "en",
//components: [Component(Component.country, "in")]
);
displayPrediction(prediction);
}
void onError(PlacesAutocompleteResponse response) {
homeScaffoldKey.currentState!.showSnackBar(
SnackBar(content: Text(response.errorMessage!)),
);}
Upvotes: 0
Reputation: 181
I have same issue with you. actually google autocomplete can be done by basic HTTP API request. I have create some article on it called "Your Own - Flutter Google Places Autocomplete.
I have done this by basic async HTTP Request. First you must set a controller and put listener at initialization for your TextField
TextField(
controller: _controller,
decoration: InputDecoration(
hintText: "Seek your location here",
focusColor: Colors.white,
floatingLabelBehavior: FloatingLabelBehavior.never,
prefixIcon: Icon(Icons.map),
suffixIcon: IconButton(
icon: Icon(Icons.cancel),
),
),
),
The _controller
should be like this:
var _controller = TextEditingController();
And you must register a listener at your initState()
@override
void initState() {
super.initState();
_controller.addListener(() {
_onChanged();
});
}
_onChange
function can you define as an asynchronous function to call the standard API request for Google Places Autocomplete
that provided by Google
https://maps.googleapis.com/maps/api/place/autocomplete/json?
please refer to this link for better understanding about the Google Place Autocomplete.
Don't forget to add session token so your billing will secure :)
sessiontoken
— A random string which identifies an autocomplete session for billing purposes. If this parameter is omitted from an autocomplete request, the request is billed independently. See the pricing sheet for details.
And for the last, here is the complete code for _onChange
function:
_onChanged() {
if (_sessionToken == null) {
setState(() {
_sessionToken = uuid.v4();
});
}
getSuggestion(_controller.text);
}
void getSuggestion(String input) async {
String kPLACES_API_KEY = "CHANGE THIS WITH YOUR GOOGLE API KEY";
String type = '(regions)';
String baseURL =
'https://maps.googleapis.com/maps/api/place/autocomplete/json';
String request =
'$baseURL?input=$input&key=$kPLACES_API_KEY&sessiontoken=$_sessionToken';
var response = await http.get(request);
if (response.statusCode == 200) {
setState(() {
_placeList = json.decode(response.body)['predictions'];
});
} else {
throw Exception('Failed to load predictions');
}
}
your must declare List<dynamic> _placeList = [];
at initial of Widget.
and the bonus, how we displaying the List
of suggestion is like this:
ListView.builder(
physics: NeverScrollableScrollPhysics(),
shrinkWrap: true,
itemCount: _placeList.length,
itemBuilder: (context, index) {
return ListTile(
title: Text(_placeList[index]["description"]),
);
},
),
put this under your TextField widget.
for grab working code please refer this github link below (add the package by your own!):
https://github.com/cmailoa/google_places_autocomplete
for further explanation please check the link bellow.
https://link.medium.com/7fq2hr2WZ9
Upvotes: 11