Есть ли способ реализовать автозаполнение мест Google во Flutter?

Я впервые использую Flutter для создания мобильного приложения, и я не нашел способа реализовать автозаполнение мест Google в компоненте textEdit. Я стремлюсь получить своего рода представление списка, пока пользователь вводит местоположение, как мы можем сделать в собственной реализации Android / iOS и react / ionic.

Я получил компонент TextEdit, который ищет возможные местоположения и выбирает первое в конце. Вот фрагмент моего кода

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


}

Как мы видим из Geolocator, мы можем получить какое-то местоположение на основе адреса, который мы вводим (следовательно, мы можем взять результаты оттуда), но я не нашел разумного способа реализовать часть предложений текстовых сообщений.


person stefanodecillis    schedule 11.03.2020    source источник
comment
Надеюсь, это поможет medium.com/flutter-community/   -  person A R    schedule 11.03.2020


Ответы (2)


У меня с тобой такая же проблема. на самом деле автозаполнение Google может быть выполнено с помощью базового запроса HTTP API. Я написал об этом статью под названием Your Own - Flutter Google Places Autocomplete.

Я сделал это с помощью базового асинхронного HTTP-запроса. Сначала вы должны установить контроллер и поместить слушателя при инициализации для вашего 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),
    ),
  ),
),

_controller должен быть таким:

var _controller = TextEditingController();

И вы должны зарегистрировать слушателя на своем initState()

@override
void initState() {
  super.initState();
  _controller.addListener(() {
    _onChanged();
  });
}

_onChange можно определить как асинхронную функцию для вызова стандартного запроса API для Google Places Autocomplete, предоставленного Google.

https://maps.googleapis.com/maps/api/place/autocomplete/json?

пожалуйста, обратитесь к этой ссылке, чтобы лучше понять автозаполнение Google Place.

Не забудьте добавить токен сеанса, чтобы обеспечить безопасность вашего биллинга: )

sessiontoken - случайная строка, определяющая сеанс автозаполнения для выставления счетов. Если этот параметр не указан в запросе автозаполнения, запрос оплачивается отдельно. См. Подробности в прайс-листе.

И напоследок полный код функции _onChange:

_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');
  }
}

вы должны объявить List<dynamic> _placeList = []; в начале виджета.

и бонус, как мы отображаем List предложения, выглядит следующим образом:

ListView.builder(
  physics: NeverScrollableScrollPhysics(),
  shrinkWrap: true,
  itemCount: _placeList.length,
  itemBuilder: (context, index) {
    return ListTile(
      title: Text(_placeList[index]["description"]),
    );
  },
),

поместите это под виджет TextField.

для получения рабочего кода обратитесь к этой ссылке на github ниже (добавьте пакет самостоятельно!):

https://github.com/cmailoa/google_places_autocomplete

для дальнейшего объяснения, пожалуйста, проверьте ссылку ниже.

https://link.medium.com/7fq2hr2WZ9

person CH Andre Mailoa    schedule 22.09.2020
comment
Хотя эта ссылка может дать ответ на вопрос, лучше включить сюда основные части ответа и предоставить ссылку для справки. Ответы, содержащие только ссылки, могут стать недействительными, если ссылка на страницу изменится. - Из отзыва - person Chris; 23.09.2020
comment
Это не совсем ответ на вопрос. Если у вас есть другой вопрос, вы можете задать его, нажав Задать вопрос. Вы также можете добавить вознаграждение, чтобы привлечь больше внимания к этому вопросу, когда у вас будет достаточно reputation. - Из отзыва - person kk.; 23.09.2020
comment
Спасибо, что сообщили мне об этом. Я изменил свои ответы .. Просто поделитесь тем, что я знаю - person CH Andre Mailoa; 23.09.2020
comment
Большое спасибо! Кстати, как я могу получить токен сеанса ?! - person GI HYUN NAM; 30.12.2020
comment
@GIHYUNNAM Насколько я знаю, вы просто создаете случайный символ, соответствующий стандарту UUID для этого. В ответах было написано _sessionToken = uuid.v4(); для генерации uuid для вашей сессии. - person CH Andre Mailoa; 03.01.2021
comment
Поскольку API вызывается для каждой набранной буквы, не съест ли это ограничение на количество запросов api для автозаполнения? Или, скорее, стать ОЧЕНЬ дорого по мере масштабирования приложения? - person Jose Tapizquent; 10.01.2021
comment
@JoseTapizquent да, вы правы, поэтому Google предоставляет сеанс. Это будет взиматься с нас за каждую завершенную сессию, а не за каждое напечатанное письмо. За исключением того, что вы не создавали сеансы, тогда с вас будет взиматься очень высокая плата :) Как вы заметили, в приведенном ниже примере запроса из документов Google конечные строки содержат токен сеанса maps.googleapis.com/maps/api/place/autocomplete/ - person CH Andre Mailoa; 09.03.2021

Есть гугл места и места автозаполнения флаттер-пакетов. Вот ссылки flutter_google_places, flutter_google_places_autocomplete.

person Akshay Kumar S    schedule 11.03.2020
comment
Я уже нашел эти пакеты, но они создают только панель поиска (как новый экран). Я ожидал чего-то вроде списка под компонентом textEdit, как мы видим в других фреймворках, но я думаю, что у нас нет такого инструмента в данный момент во флаттере. - person stefanodecillis; 12.03.2020