From c9a1c2d5b67ae8bd24bcc22f8afd207f65f51c78 Mon Sep 17 00:00:00 2001 From: kundan Date: Wed, 3 Apr 2024 13:53:36 +0530 Subject: [PATCH] focus node and form callback --- example/pubspec.lock | 68 ++++++++++++++++++--------- lib/google_places_flutter.dart | 84 ++++++++++++++++++++++------------ lib/model/place_details.dart | 11 +++-- 3 files changed, 109 insertions(+), 54 deletions(-) diff --git a/example/pubspec.lock b/example/pubspec.lock index 5967b8c..a7831af 100644 --- a/example/pubspec.lock +++ b/example/pubspec.lock @@ -45,10 +45,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" cupertino_icons: dependency: "direct main" description: @@ -89,7 +89,7 @@ packages: path: ".." relative: true source: path - version: "2.0.6" + version: "2.0.7" http_parser: dependency: transitive description: @@ -98,38 +98,62 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.0" + leak_tracker: + dependency: transitive + description: + name: leak_tracker + sha256: "78eb209deea09858f5269f5a5b02be4049535f568c07b275096836f01ea323fa" + url: "https://pub.dev" + source: hosted + version: "10.0.0" + leak_tracker_flutter_testing: + dependency: transitive + description: + name: leak_tracker_flutter_testing + sha256: b46c5e37c19120a8a01918cfaf293547f47269f7cb4b0058f21531c2465d6ef0 + url: "https://pub.dev" + source: hosted + version: "2.0.1" + leak_tracker_testing: + dependency: transitive + description: + name: leak_tracker_testing + sha256: a597f72a664dbd293f3bfc51f9ba69816f84dcd403cdac7066cb3f6003f3ab47 + url: "https://pub.dev" + source: hosted + version: "2.0.1" matcher: dependency: transitive description: name: matcher - sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e" + sha256: d2323aa2060500f906aa31a895b4030b6da3ebdcc5619d14ce1aada65cd161cb url: "https://pub.dev" source: hosted - version: "0.12.16" + version: "0.12.16+1" material_color_utilities: dependency: transitive description: name: material_color_utilities - sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41" + sha256: "0e0a020085b65b6083975e499759762399b4475f766c21668c4ecca34ea74e5a" url: "https://pub.dev" source: hosted - version: "0.5.0" + version: "0.8.0" meta: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: d584fa6707a52763a52446f02cc621b077888fb63b93bbcb1143a7be5a0c0c04 url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.11.0" path: dependency: transitive description: name: path - sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917" + sha256: "087ce49c3f0dc39180befefc60fdb4acd8f8620e5682fe2476afd0b3688bb4af" url: "https://pub.dev" source: hosted - version: "1.8.3" + version: "1.9.0" rxdart: dependency: transitive description: @@ -155,18 +179,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" string_scanner: dependency: transitive description: @@ -187,10 +211,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" typed_data: dependency: transitive description: @@ -207,13 +231,13 @@ packages: url: "https://pub.dev" source: hosted version: "2.1.4" - web: + vm_service: dependency: transitive description: - name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + name: vm_service + sha256: b3d56ff4341b8f182b96aceb2fa20e3dcb336b9f867bc0eafc0de10f1048e957 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "13.0.0" sdks: - dart: ">=3.1.0-185.0.dev <4.0.0" + dart: ">=3.2.0-0 <4.0.0" diff --git a/lib/google_places_flutter.dart b/lib/google_places_flutter.dart index 8c0320c..c6924cd 100644 --- a/lib/google_places_flutter.dart +++ b/lib/google_places_flutter.dart @@ -1,16 +1,17 @@ library google_places_flutter; +import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; -import 'package:google_places_flutter/model/place_details.dart'; -import 'package:google_places_flutter/model/prediction.dart'; import 'package:rxdart/subjects.dart'; import 'package:dio/dio.dart'; import 'package:rxdart/rxdart.dart'; import 'DioErrorHandler.dart'; +import 'model/place_details.dart'; +import 'model/prediction.dart'; class GooglePlaceAutoCompleteTextField extends StatefulWidget { InputDecoration inputDecoration; @@ -31,22 +32,33 @@ class GooglePlaceAutoCompleteTextField extends StatefulWidget { bool showError; double? containerHorizontalPadding; double? containerVerticalPadding; + FocusNode? focusNode; + TextInputAction? textInputAction; + final VoidCallback? formSubmitCallback; + + + GooglePlaceAutoCompleteTextField( {required this.textEditingController, required this.googleAPIKey, - this.debounceTime: 600, - this.inputDecoration: const InputDecoration(), + this.debounceTime = 600, + this.formSubmitCallback, + this.inputDecoration = const InputDecoration(), this.itemClick, this.isLatLngRequired = true, - this.textStyle: const TextStyle(), + this.textStyle = const TextStyle(), this.countries, this.getPlaceDetailWithLatLng, this.itemBuilder, this.boxDecoration, this.isCrossBtnShown = true, - this.seperatedBuilder,this.showError=true,this - .containerHorizontalPadding,this.containerVerticalPadding}); + this.seperatedBuilder, + this.showError = true, + this.textInputAction = TextInputAction.done, + this.containerHorizontalPadding, + this.containerVerticalPadding, + this.focusNode}); @override _GooglePlaceAutoCompleteTextFieldState createState() => @@ -68,16 +80,14 @@ class _GooglePlaceAutoCompleteTextFieldState CancelToken? _cancelToken = CancelToken(); - - - @override Widget build(BuildContext context) { - return CompositedTransformTarget( link: _layerLink, child: Container( - padding: EdgeInsets.symmetric(horizontal: widget.containerHorizontalPadding??0, vertical: widget.containerVerticalPadding??0), + padding: EdgeInsets.symmetric( + horizontal: widget.containerHorizontalPadding ?? 0, + vertical: widget.containerVerticalPadding ?? 0), alignment: Alignment.centerLeft, decoration: widget.boxDecoration ?? BoxDecoration( @@ -93,6 +103,11 @@ class _GooglePlaceAutoCompleteTextFieldState decoration: widget.inputDecoration, style: widget.textStyle, controller: widget.textEditingController, + focusNode: widget.focusNode ?? FocusNode(), + textInputAction: widget.textInputAction, + onFieldSubmitted: (value) { + widget.formSubmitCallback!(); + }, onChanged: (string) { subject.add(string); if (widget.isCrossBtnShown) { @@ -114,7 +129,7 @@ class _GooglePlaceAutoCompleteTextFieldState } getLocation(String text) async { - String url = + String apiURL = "https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$text&key=${widget.googleAPIKey}"; if (widget.countries != null) { @@ -124,9 +139,9 @@ class _GooglePlaceAutoCompleteTextFieldState String country = widget.countries![i]; if (i == 0) { - url = url + "&components=country:$country"; + apiURL = apiURL + "&components=country:$country"; } else { - url = url + "|" + "country:" + country; + apiURL = apiURL + "|" + "country:" + country; } } } @@ -136,8 +151,14 @@ class _GooglePlaceAutoCompleteTextFieldState _cancelToken = CancelToken(); } - try { + String proxyURL = "https://cors-anywhere.herokuapp.com/"; + String url = kIsWeb ? proxyURL + apiURL : apiURL; + + /// Add the custom header to the options + final options = kIsWeb + ? Options(headers: {"x-requested-with": "XMLHttpRequest"}) + : null; Response response = await _dio.get(url); ScaffoldMessenger.of(context).hideCurrentSnackBar(); @@ -157,11 +178,11 @@ class _GooglePlaceAutoCompleteTextFieldState isSearched = false; alPredictions.clear(); - if (subscriptionResponse.predictions!.length > 0 && (widget.textEditingController.text.toString().trim()).isNotEmpty) { + if (subscriptionResponse.predictions!.length > 0 && + (widget.textEditingController.text.toString().trim()).isNotEmpty) { alPredictions.addAll(subscriptionResponse.predictions!); } - this._overlayEntry = null; this._overlayEntry = this._createOverlayEntry(); Overlay.of(context)!.insert(this._overlayEntry!); @@ -245,18 +266,24 @@ class _GooglePlaceAutoCompleteTextFieldState Future getPlaceDetailsFromPlaceId(Prediction prediction) async { //String key = GlobalConfiguration().getString('google_maps_key'); - var url = - "https://maps.googleapis.com/maps/api/place/details/json?placeid=${prediction.placeId}&key=${widget.googleAPIKey}"; - Response response = await Dio().get( - url, - ); + var url = "https://maps.googleapis.com/maps/api/place/details/json?placeid=${prediction.placeId}&key=${widget.googleAPIKey}"; + try { + Response response = await _dio.get( + url, + ); + - PlaceDetails placeDetails = PlaceDetails.fromJson(response.data); + PlaceDetails placeDetails = PlaceDetails.fromJson(response.data); - prediction.lat = placeDetails.result!.geometry!.location!.lat.toString(); - prediction.lng = placeDetails.result!.geometry!.location!.lng.toString(); + prediction.lat = placeDetails.result!.geometry!.location!.lat.toString(); + prediction.lng = placeDetails.result!.geometry!.location!.lng.toString(); - widget.getPlaceDetailWithLatLng!(prediction); + widget.getPlaceDetailWithLatLng!(prediction); + } + catch(e){ + var errorHandler = ErrorHandler.internal().handleError(e); + _showSnackBar("${errorHandler.message}"); + } } void clearData() { @@ -282,7 +309,7 @@ class _GooglePlaceAutoCompleteTextFieldState } _showSnackBar(String errorData) { - if(widget.showError){ + if (widget.showError) { final snackBar = SnackBar( content: Text("$errorData"), ); @@ -291,7 +318,6 @@ class _GooglePlaceAutoCompleteTextFieldState // and use it to show a SnackBar. ScaffoldMessenger.of(context).showSnackBar(snackBar); } - } } diff --git a/lib/model/place_details.dart b/lib/model/place_details.dart index d831ea2..f3cdb38 100644 --- a/lib/model/place_details.dart +++ b/lib/model/place_details.dart @@ -70,7 +70,7 @@ class Result { icon = json['icon']; name = json['name']; if (json['photos'] != null) { - photos =[]; + photos = []; json['photos'].forEach((v) { photos!.add(new Photos.fromJson(v)); }); @@ -169,8 +169,13 @@ class Location { Location({this.lat, this.lng}); Location.fromJson(Map json) { - lat = json['lat']; - lng = json['lng']; + + if (json["lat"] != null) { + lat = double.parse(json["lat"].toString()); + } + if (json["lng"] != null) { + lng = double.parse(json["lng"].toString()); + } } Map toJson() {