stefanodecillis
stefanodecillis

Reputation: 180

Is there a way to implement Google places autocomplete in Flutter?

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

Answers (3)

Please use onChanged instead of listener.

Upvotes: 0

Hardik Chitroda
Hardik Chitroda

Reputation: 67

Google places autocomplete widgets for flutter.


  • dependencies : flutter: sdk: flutter flutter_google_places_hoc081098: ^1.0.0-nullsafety.4

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!)),
);}

Fore more information...

Upvotes: 0

CH Andre Mailoa
CH Andre Mailoa

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

Related Questions