diff --git a/CHANGELOG.md b/CHANGELOG.md
index a4443b6..dc2d6e6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -25,3 +25,11 @@
## 2.0.5
* Support Null Safety and code improvement
+
+## 2.0.6
+
+* Support custom list item builder, error handled and minor fixes
+
+## 2.0.7
+
+* Update dio dependency and minor improvements
diff --git a/README.md b/README.md
index adfbe39..e03de98 100644
--- a/README.md
+++ b/README.md
@@ -12,7 +12,6 @@ dependencies:
# Google AutoComplete TextField Widget code
-
```
GooglePlaceAutoCompleteTextField(
textEditingController: controller,
@@ -29,12 +28,40 @@ dependencies:
controller.text=prediction.description;
controller.selection = TextSelection.fromPosition(TextPosition(offset: prediction.description.length));
}
+ // if we want to make custom list item builder
+ itemBuilder: (context, index, Prediction prediction) {
+ return Container(
+ padding: EdgeInsets.all(10),
+ child: Row(
+ children: [
+ Icon(Icons.location_on),
+ SizedBox(
+ width: 7,
+ ),
+ Expanded(child: Text("${prediction.description??""}"))
+ ],
+ ),
+ );
+ }
+ // if you want to add seperator between list items
+ seperatedBuilder: Divider(),
+ // want to show close icon
+ isCrossBtnShown: true,
+ // optional container padding
+ containerHorizontalPadding: 10,
+
+
+
+
)
```
+
# Customization Option
- You can customize a text field input decoration and debounce time
+
+You can customize a text field input decoration and debounce time
# Screenshorts
+
diff --git a/example/android/app/build.gradle b/example/android/app/build.gradle
index 0f6a5e5..8ffc107 100644
--- a/example/android/app/build.gradle
+++ b/example/android/app/build.gradle
@@ -26,7 +26,7 @@ apply plugin: 'kotlin-android'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
android {
- compileSdkVersion 28
+ compileSdkVersion 33
sourceSets {
main.java.srcDirs += 'src/main/kotlin'
@@ -40,7 +40,7 @@ android {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.example.example"
minSdkVersion 16
- targetSdkVersion 28
+ targetSdkVersion 33
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
@@ -53,6 +53,16 @@ android {
signingConfig signingConfigs.debug
}
}
+
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ kotlinOptions {
+ jvmTarget = 1.8
+ }
+
+ namespace 'com.example.example'
}
flutter {
diff --git a/example/android/app/src/main/AndroidManifest.xml b/example/android/app/src/main/AndroidManifest.xml
index 7913ba0..fe45692 100644
--- a/example/android/app/src/main/AndroidManifest.xml
+++ b/example/android/app/src/main/AndroidManifest.xml
@@ -8,7 +8,7 @@
diff --git a/example/android/build.gradle b/example/android/build.gradle
index 3100ad2..0cb092f 100644
--- a/example/android/build.gradle
+++ b/example/android/build.gradle
@@ -1,12 +1,12 @@
buildscript {
- ext.kotlin_version = '1.3.50'
+ ext.kotlin_version = '1.8.21'
repositories {
google()
jcenter()
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.5.0'
+ classpath 'com.android.tools.build:gradle:8.0.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
@@ -26,6 +26,6 @@ subprojects {
project.evaluationDependsOn(':app')
}
-task clean(type: Delete) {
+tasks.register("clean", Delete) {
delete rootProject.buildDir
}
diff --git a/example/android/gradle/wrapper/gradle-wrapper.properties b/example/android/gradle/wrapper/gradle-wrapper.properties
index 296b146..55de1e6 100644
--- a/example/android/gradle/wrapper/gradle-wrapper.properties
+++ b/example/android/gradle/wrapper/gradle-wrapper.properties
@@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
diff --git a/example/lib/main.dart b/example/lib/main.dart
index c566e10..f9bb777 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -19,9 +19,9 @@ class MyApp extends StatelessWidget {
}
class MyHomePage extends StatefulWidget {
- MyHomePage({Key key, this.title}) : super(key: key);
+ MyHomePage({Key? key, this.title}) : super(key: key);
- final String title;
+ final String? title;
@override
_MyHomePageState createState() => _MyHomePageState();
@@ -36,7 +36,7 @@ class _MyHomePageState extends State {
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
- title: Text(widget.title),
+ title: Text(widget.title ?? ""),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
@@ -70,23 +70,48 @@ class _MyHomePageState extends State {
return Container(
padding: EdgeInsets.symmetric(horizontal: 20),
child: GooglePlaceAutoCompleteTextField(
- textEditingController: controller,
- googleAPIKey: "YOUR_GOOGLE_API_KEY",
- inputDecoration: InputDecoration(hintText: "Search your location"),
- debounceTime: 800,
- countries: ["in", "fr"],
- isLatLngRequired: true,
- getPlaceDetailWithLatLng: (Prediction prediction) {
- print("placeDetails" + prediction.lng.toString());
- },
- itmClick: (Prediction prediction) {
- controller.text = prediction.description;
+ textEditingController: controller,
+ googleAPIKey:"YOUR_GOOGLE_API_KEY",
+ inputDecoration: InputDecoration(
+ hintText: "Search your location",
+ border: InputBorder.none,
+ enabledBorder: InputBorder.none,
+ ),
+ debounceTime: 400,
+ countries: ["in", "fr"],
+ isLatLngRequired: false,
+ getPlaceDetailWithLatLng: (Prediction prediction) {
+ print("placeDetails" + prediction.lat.toString());
+ },
+
+ itemClick: (Prediction prediction) {
+ controller.text = prediction.description ?? "";
+ controller.selection = TextSelection.fromPosition(
+ TextPosition(offset: prediction.description?.length ?? 0));
+ },
+ seperatedBuilder: Divider(),
+ containerHorizontalPadding: 10,
+
+ // OPTIONAL// If you want to customize list view item builder
+ itemBuilder: (context, index, Prediction prediction) {
+ return Container(
+ padding: EdgeInsets.all(10),
+ child: Row(
+ children: [
+ Icon(Icons.location_on),
+ SizedBox(
+ width: 7,
+ ),
+ Expanded(child: Text("${prediction.description??""}"))
+ ],
+ ),
+ );
+ },
- controller.selection = TextSelection.fromPosition(
- TextPosition(offset: prediction.description.length));
- }
- // default 600 ms ,
- ),
+ isCrossBtnShown: true,
+
+ // default 600 ms ,
+ ),
);
}
}
diff --git a/example/pubspec.lock b/example/pubspec.lock
index a0212ba..5967b8c 100644
--- a/example/pubspec.lock
+++ b/example/pubspec.lock
@@ -5,65 +5,74 @@ packages:
dependency: transitive
description:
name: async
- url: "https://pub.dartlang.org"
+ sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ url: "https://pub.dev"
source: hosted
- version: "2.6.1"
+ version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
- url: "https://pub.dartlang.org"
+ sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
characters:
dependency: transitive
description:
name: characters
- url: "https://pub.dartlang.org"
+ sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.3.0"
charcode:
dependency: transitive
description:
name: charcode
- url: "https://pub.dartlang.org"
+ sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
+ url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.3.1"
clock:
dependency: transitive
description:
name: clock
- url: "https://pub.dartlang.org"
+ sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
- url: "https://pub.dartlang.org"
+ sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
+ url: "https://pub.dev"
source: hosted
- version: "1.15.0"
+ version: "1.17.2"
cupertino_icons:
dependency: "direct main"
description:
name: cupertino_icons
- url: "https://pub.dartlang.org"
+ sha256: e35129dc44c9118cee2a5603506d823bab99c68393879edb440e0090d07586be
+ url: "https://pub.dev"
source: hosted
- version: "0.1.3"
+ version: "1.0.5"
dio:
dependency: transitive
description:
name: dio
- url: "https://pub.dartlang.org"
+ sha256: "797e1e341c3dd2f69f2dad42564a6feff3bfb87187d05abb93b9609e6f1645c3"
+ url: "https://pub.dev"
source: hosted
- version: "4.0.0"
+ version: "5.4.0"
fake_async:
dependency: transitive
description:
name: fake_async
- url: "https://pub.dartlang.org"
+ sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
@@ -80,40 +89,53 @@ packages:
path: ".."
relative: true
source: path
- version: "2.0.4"
+ version: "2.0.6"
http_parser:
dependency: transitive
description:
name: http_parser
- url: "https://pub.dartlang.org"
+ sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185
+ url: "https://pub.dev"
source: hosted
version: "4.0.0"
matcher:
dependency: transitive
description:
name: matcher
- url: "https://pub.dartlang.org"
+ sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
+ url: "https://pub.dev"
source: hosted
- version: "0.12.10"
+ version: "0.12.16"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.5.0"
meta:
dependency: transitive
description:
name: meta
- url: "https://pub.dartlang.org"
+ sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+ url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.9.1"
path:
dependency: transitive
description:
name: path
- url: "https://pub.dartlang.org"
+ sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
+ url: "https://pub.dev"
source: hosted
- version: "1.8.0"
+ version: "1.8.3"
rxdart:
dependency: transitive
description:
name: rxdart
- url: "https://pub.dartlang.org"
+ sha256: "7358d9e183dd9002a16c17200186c7af56dd9e210b030853ca669ccd02e3d5d6"
+ url: "https://pub.dev"
source: hosted
version: "0.27.2"
sky_engine:
@@ -125,57 +147,73 @@ packages:
dependency: transitive
description:
name: source_span
- url: "https://pub.dartlang.org"
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
source: hosted
- version: "1.8.1"
+ version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
- url: "https://pub.dartlang.org"
+ sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ url: "https://pub.dev"
source: hosted
- version: "1.10.0"
+ version: "1.11.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
- url: "https://pub.dartlang.org"
+ sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
- url: "https://pub.dartlang.org"
+ sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+ url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
- url: "https://pub.dartlang.org"
+ sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
- url: "https://pub.dartlang.org"
+ sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
+ url: "https://pub.dev"
source: hosted
- version: "0.3.0"
+ version: "0.6.0"
typed_data:
dependency: transitive
description:
name: typed_data
- url: "https://pub.dartlang.org"
+ sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee"
+ url: "https://pub.dev"
source: hosted
version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
- url: "https://pub.dartlang.org"
+ sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+ url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "0.1.4-beta"
sdks:
- dart: ">=2.12.0 <3.0.0"
+ dart: ">=3.1.0-185.0.dev <4.0.0"
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 9841a8d..20d3a3d 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -14,7 +14,7 @@ description: A new Flutter application.
version: 1.0.0+1
environment:
- sdk: ">=2.1.0 <3.0.0"
+ sdk: ">=2.12.0 <4.0.0"
dependencies:
flutter:
@@ -22,7 +22,7 @@ dependencies:
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
- cupertino_icons: ^0.1.2
+ cupertino_icons: ^1.0.1
google_places_flutter:
path: ../
diff --git a/lib/DioErrorHandler.dart b/lib/DioErrorHandler.dart
new file mode 100644
index 0000000..006149e
--- /dev/null
+++ b/lib/DioErrorHandler.dart
@@ -0,0 +1,150 @@
+import 'package:dio/dio.dart';
+
+import 'error_response.dart';
+
+class DioErrorHandler {
+ ErrorResponse errorResponse = ErrorResponse();
+ String errorDescription = "";
+
+
+
+
+ ErrorResponse handleDioError(DioException dioError) {
+ switch (dioError.type) {
+ case DioExceptionType.cancel:
+
+ errorResponse.message = "Request to API server was cancelled";
+ break;
+ case DioExceptionType.connectionTimeout:
+ errorResponse.message = "Connection timeout with API server";
+ break;
+ case DioExceptionType.unknown:
+
+ if((dioError.message?.contains("RedirectException")??false)){
+ errorResponse.message = "${dioError.message}";
+ }else {
+ errorResponse.message = "Please check the internet connection";
+ }
+ break;
+ case DioExceptionType.receiveTimeout:
+
+ errorResponse.message = "Receive timeout in connection with API server";
+ break;
+ case DioExceptionType.badResponse:
+ try {
+
+ if (dioError.response?.data['message'] != null) {
+ errorResponse.message = dioError.response?.data['message'];
+ } else {
+ if ((dioError.response?.statusMessage ?? "").isNotEmpty)
+ errorResponse.message = dioError.response?.statusMessage;
+ else
+ return _handleError(
+ dioError.response!.statusCode, dioError.response!.data);
+ }
+ } catch (e) {
+
+ if ((dioError.response?.statusMessage ?? "").isNotEmpty)
+ errorResponse.message = dioError.response?.statusMessage;
+ else
+ return _handleError(
+ dioError.response!.statusCode, dioError.response!.data);
+ }
+
+ break;
+ case DioExceptionType.sendTimeout:
+
+ errorResponse.message = "Send timeout in connection with API server";
+ break;
+ default:
+
+ errorResponse.message = "Something went wrong";
+ break;
+ }
+ return errorResponse;
+ }
+
+ ErrorResponse _handleError(int? statusCode, dynamic error) {
+ switch (statusCode) {
+ case 400:
+ return getMas(error);
+ // case 401:
+ // return checkTokenExpire(error);
+ case 404:
+ return getMas(error);
+ case 403:
+ return getMas(error);
+ case 500:
+ errorResponse.message = 'Internal server error';
+ return errorResponse;
+ default:
+ return getUnKnownMes(error);
+ }
+ }
+
+ // checkTokenExpire(error) {
+ // // print("my error ${error}");
+ // if (error['msg'].toString().toLowerCase() ==
+ // "Token has expired".toLowerCase()) {
+ // UIData.tokenExpire(error['msg']);
+ // return;
+ // }
+ // errorResponse.message = error['msg'].toString();
+ // return errorResponse;
+ // }
+
+ getMas(dynamic error) {
+ print("myError ${error.runtimeType}");
+ if (error.runtimeType != String) {
+ errorResponse.message =
+ error['message'].toString(); //?? S.of(Get.context).something_wrong;
+ } else {
+ if (error['msg'] != null) {
+ errorResponse.message = error['msg'].toString();
+ } else {
+ errorResponse.message = "Something Wrong";
+ } //S.of(Get.context).something_wrong;
+ }
+ return errorResponse;
+ }
+
+ getUnKnownMes(dynamic error) {
+ if (error['msg'] != null) {
+ errorResponse.message = error['msg'].toString();
+ } else if (error['message'] != null) {
+ errorResponse.message = error['message'].toString();
+ } else {
+ errorResponse.message = "Something went wrong";
+ }
+ return errorResponse;
+ }
+}
+
+
+class ErrorHandler {
+
+ static final ErrorHandler _inst=ErrorHandler.internal();
+ ErrorHandler.internal();
+
+ factory ErrorHandler() {
+ return _inst;
+ }
+ ErrorResponse errorResponse=ErrorResponse();
+
+ ErrorResponse handleError(var error) {
+ if(error.runtimeType.toString().toLowerCase() =="_TypeError".toLowerCase()){
+ // return error.toString();
+ errorResponse.message ="The Provided API key is invalid";
+ return errorResponse;
+ }
+
+
+ else if(error is DioException) {
+ return DioErrorHandler().handleDioError(error);
+ }
+ errorResponse.message = "The Provided API key is invalid";
+ return errorResponse;
+ }
+
+
+}
\ No newline at end of file
diff --git a/lib/error_response.dart b/lib/error_response.dart
new file mode 100644
index 0000000..8fb8150
--- /dev/null
+++ b/lib/error_response.dart
@@ -0,0 +1,20 @@
+class ErrorResponse {
+ String? message;
+ int? status;
+
+ ErrorResponse( {this.message, this.status});
+
+ ErrorResponse.fromJson(Map json) {
+ message = json['message'];
+ status = json['status'];
+
+ }
+
+ Map toJson() {
+ final Map data = {};
+ data['message'] = message;
+ data['status'] = status;
+
+ return data;
+ }
+}
\ No newline at end of file
diff --git a/lib/google_places_flutter.dart b/lib/google_places_flutter.dart
index 4c37024..8c0320c 100644
--- a/lib/google_places_flutter.dart
+++ b/lib/google_places_flutter.dart
@@ -1,6 +1,5 @@
library google_places_flutter;
-import 'dart:convert';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
@@ -11,9 +10,11 @@ import 'package:rxdart/subjects.dart';
import 'package:dio/dio.dart';
import 'package:rxdart/rxdart.dart';
+import 'DioErrorHandler.dart';
+
class GooglePlaceAutoCompleteTextField extends StatefulWidget {
InputDecoration inputDecoration;
- ItemClick? itmClick;
+ ItemClick? itemClick;
GetPlaceDetailswWithLatLng? getPlaceDetailWithLatLng;
bool isLatLngRequired = true;
@@ -22,18 +23,30 @@ class GooglePlaceAutoCompleteTextField extends StatefulWidget {
int debounceTime = 600;
List? countries = [];
TextEditingController textEditingController = TextEditingController();
+ ListItemBuilder? itemBuilder;
+ Widget? seperatedBuilder;
+ void clearData;
+ BoxDecoration? boxDecoration;
+ bool isCrossBtnShown;
+ bool showError;
+ double? containerHorizontalPadding;
+ double? containerVerticalPadding;
GooglePlaceAutoCompleteTextField(
{required this.textEditingController,
required this.googleAPIKey,
this.debounceTime: 600,
this.inputDecoration: const InputDecoration(),
- this.itmClick,
- this.isLatLngRequired=true,
+ this.itemClick,
+ this.isLatLngRequired = true,
this.textStyle: const TextStyle(),
this.countries,
this.getPlaceDetailWithLatLng,
- });
+ this.itemBuilder,
+ this.boxDecoration,
+ this.isCrossBtnShown = true,
+ this.seperatedBuilder,this.showError=true,this
+ .containerHorizontalPadding,this.containerVerticalPadding});
@override
_GooglePlaceAutoCompleteTextFieldState createState() =>
@@ -50,21 +63,57 @@ class _GooglePlaceAutoCompleteTextFieldState
final LayerLink _layerLink = LayerLink();
bool isSearched = false;
+ bool isCrossBtn = true;
+ late var _dio;
+
+ CancelToken? _cancelToken = CancelToken();
+
+
+
+
@override
Widget build(BuildContext context) {
+
return CompositedTransformTarget(
link: _layerLink,
- child: TextFormField(
- decoration: widget.inputDecoration,
- style: widget.textStyle,
- controller: widget.textEditingController,
- onChanged: (string) => (subject.add(string)),
+ child: Container(
+ padding: EdgeInsets.symmetric(horizontal: widget.containerHorizontalPadding??0, vertical: widget.containerVerticalPadding??0),
+ alignment: Alignment.centerLeft,
+ decoration: widget.boxDecoration ??
+ BoxDecoration(
+ shape: BoxShape.rectangle,
+ border: Border.all(color: Colors.grey, width: 0.6),
+ borderRadius: BorderRadius.all(Radius.circular(10))),
+ child: Row(
+ mainAxisSize: MainAxisSize.max,
+ crossAxisAlignment: CrossAxisAlignment.center,
+ children: [
+ Expanded(
+ child: TextFormField(
+ decoration: widget.inputDecoration,
+ style: widget.textStyle,
+ controller: widget.textEditingController,
+ onChanged: (string) {
+ subject.add(string);
+ if (widget.isCrossBtnShown) {
+ isCrossBtn = string.isNotEmpty ? true : false;
+ setState(() {});
+ }
+ },
+ ),
+ ),
+ (!widget.isCrossBtnShown)
+ ? SizedBox()
+ : isCrossBtn && _showCrossIconWidget()
+ ? IconButton(onPressed: clearData, icon: Icon(Icons.close))
+ : SizedBox()
+ ],
+ ),
),
);
}
getLocation(String text) async {
- Dio dio = new Dio();
String url =
"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=$text&key=${widget.googleAPIKey}";
@@ -82,34 +131,50 @@ class _GooglePlaceAutoCompleteTextFieldState
}
}
+ if (_cancelToken?.isCancelled == false) {
+ _cancelToken?.cancel();
+ _cancelToken = CancelToken();
+ }
- Response response = await dio.get(url);
- PlacesAutocompleteResponse subscriptionResponse =
- PlacesAutocompleteResponse.fromJson(response.data);
+ try {
+ Response response = await _dio.get(url);
+ ScaffoldMessenger.of(context).hideCurrentSnackBar();
- if (text.length == 0) {
- alPredictions.clear();
- this._overlayEntry!.remove();
- return;
- }
+ Map map = response.data;
+ if (map.containsKey("error_message")) {
+ throw response.data;
+ }
+
+ PlacesAutocompleteResponse subscriptionResponse =
+ PlacesAutocompleteResponse.fromJson(response.data);
+
+ if (text.length == 0) {
+ alPredictions.clear();
+ this._overlayEntry!.remove();
+ return;
+ }
- isSearched = false;
- if (subscriptionResponse.predictions!.length > 0) {
+ isSearched = false;
alPredictions.clear();
- alPredictions.addAll(subscriptionResponse.predictions!);
- }
+ if (subscriptionResponse.predictions!.length > 0 && (widget.textEditingController.text.toString().trim()).isNotEmpty) {
+ alPredictions.addAll(subscriptionResponse.predictions!);
+ }
- //if (this._overlayEntry == null)
- this._overlayEntry = null;
- this._overlayEntry = this._createOverlayEntry();
- Overlay.of(context)!.insert(this._overlayEntry!);
- // this._overlayEntry.markNeedsBuild();
+ this._overlayEntry = null;
+ this._overlayEntry = this._createOverlayEntry();
+ Overlay.of(context)!.insert(this._overlayEntry!);
+ } catch (e) {
+ var errorHandler = ErrorHandler.internal().handleError(e);
+ _showSnackBar("${errorHandler.message}");
+ }
}
@override
void initState() {
+ super.initState();
+ _dio = Dio();
subject.stream
.distinct()
.debounceTime(Duration(milliseconds: widget.debounceTime))
@@ -135,30 +200,34 @@ class _GooglePlaceAutoCompleteTextFieldState
link: this._layerLink,
offset: Offset(0.0, size.height + 5.0),
child: Material(
- elevation: 1.0,
- child: ListView.builder(
- padding: EdgeInsets.zero,
- shrinkWrap: true,
- itemCount: alPredictions.length,
- itemBuilder: (BuildContext context, int index) {
- return InkWell(
- onTap: () {
- if (index < alPredictions.length) {
- widget.itmClick!(alPredictions[index]);
- if (!widget.isLatLngRequired) return;
-
- getPlaceDetailsFromPlaceId(
- alPredictions[index]);
-
- removeOverlay();
- }
- },
- child: Container(
+ child: ListView.separated(
+ padding: EdgeInsets.zero,
+ shrinkWrap: true,
+ itemCount: alPredictions.length,
+ separatorBuilder: (context, pos) =>
+ widget.seperatedBuilder ?? SizedBox(),
+ itemBuilder: (BuildContext context, int index) {
+ return InkWell(
+ onTap: () {
+ var selectedData = alPredictions[index];
+ if (index < alPredictions.length) {
+ widget.itemClick!(selectedData);
+
+ if (widget.isLatLngRequired) {
+ getPlaceDetailsFromPlaceId(selectedData);
+ }
+ removeOverlay();
+ }
+ },
+ child: widget.itemBuilder != null
+ ? widget.itemBuilder!(
+ context, index, alPredictions[index])
+ : Container(
padding: EdgeInsets.all(10),
child: Text(alPredictions[index].description!)),
- );
- },
- )),
+ );
+ },
+ )),
),
));
}
@@ -168,7 +237,7 @@ class _GooglePlaceAutoCompleteTextFieldState
alPredictions.clear();
this._overlayEntry = this._createOverlayEntry();
if (context != null) {
- Overlay.of(context)!.insert(this._overlayEntry!);
+ Overlay.of(context).insert(this._overlayEntry!);
this._overlayEntry!.markNeedsBuild();
}
}
@@ -188,15 +257,47 @@ class _GooglePlaceAutoCompleteTextFieldState
prediction.lng = placeDetails.result!.geometry!.location!.lng.toString();
widget.getPlaceDetailWithLatLng!(prediction);
+ }
+
+ void clearData() {
+ widget.textEditingController.clear();
+ if (_cancelToken?.isCancelled == false) {
+ _cancelToken?.cancel();
+ }
+
+ setState(() {
+ alPredictions.clear();
+ isCrossBtn = false;
+ });
+
+ if (this._overlayEntry != null) {
+ try {
+ this._overlayEntry?.remove();
+ } catch (e) {}
+ }
+ }
+
+ _showCrossIconWidget() {
+ return (widget.textEditingController.text.isNotEmpty);
+ }
+
+ _showSnackBar(String errorData) {
+ if(widget.showError){
+ final snackBar = SnackBar(
+ content: Text("$errorData"),
+ );
+
+ // Find the ScaffoldMessenger in the widget tree
+ // and use it to show a SnackBar.
+ ScaffoldMessenger.of(context).showSnackBar(snackBar);
+ }
-// prediction.latLng = new LatLng(
-// placeDetails.result.geometry.location.lat,
-// placeDetails.result.geometry.location.lng);
}
}
PlacesAutocompleteResponse parseResponse(Map responseBody) {
- return PlacesAutocompleteResponse.fromJson(responseBody as Map);
+ return PlacesAutocompleteResponse.fromJson(
+ responseBody as Map);
}
PlaceDetails parsePlaceDetailMap(Map responseBody) {
@@ -206,3 +307,6 @@ PlaceDetails parsePlaceDetailMap(Map responseBody) {
typedef ItemClick = void Function(Prediction postalCodeResponse);
typedef GetPlaceDetailswWithLatLng = void Function(
Prediction postalCodeResponse);
+
+typedef ListItemBuilder = Widget Function(
+ BuildContext context, int index, Prediction prediction);
diff --git a/pubspec.lock b/pubspec.lock
index 248816a..24f995f 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -5,58 +5,66 @@ packages:
dependency: transitive
description:
name: async
- url: "https://pub.dartlang.org"
+ sha256: "947bfcf187f74dbc5e146c9eb9c0f10c9f8b30743e341481c1e2ed3ecc18c20c"
+ url: "https://pub.dev"
source: hosted
- version: "2.6.1"
+ version: "2.11.0"
boolean_selector:
dependency: transitive
description:
name: boolean_selector
- url: "https://pub.dartlang.org"
+ sha256: "6cfb5af12253eaf2b368f07bacc5a80d1301a071c73360d746b7f2e32d762c66"
+ url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
characters:
dependency: transitive
description:
name: characters
- url: "https://pub.dartlang.org"
+ sha256: "04a925763edad70e8443c99234dc3328f442e811f1d8fd1a72f1c8ad0f69a605"
+ url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.3.0"
charcode:
dependency: transitive
description:
name: charcode
- url: "https://pub.dartlang.org"
+ sha256: fb98c0f6d12c920a02ee2d998da788bca066ca5f148492b7085ee23372b12306
+ url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.3.1"
clock:
dependency: transitive
description:
name: clock
- url: "https://pub.dartlang.org"
+ sha256: cb6d7f03e1de671e34607e909a7213e31d7752be4fb66a86d29fe1eb14bfb5cf
+ url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.1.1"
collection:
dependency: transitive
description:
name: collection
- url: "https://pub.dartlang.org"
+ sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687
+ url: "https://pub.dev"
source: hosted
- version: "1.15.0"
+ version: "1.17.2"
dio:
dependency: "direct main"
description:
name: dio
- url: "https://pub.dartlang.org"
+ sha256: "797e1e341c3dd2f69f2dad42564a6feff3bfb87187d05abb93b9609e6f1645c3"
+ url: "https://pub.dev"
source: hosted
- version: "4.0.0"
+ version: "5.4.0"
fake_async:
dependency: transitive
description:
name: fake_async
- url: "https://pub.dartlang.org"
+ sha256: "511392330127add0b769b75a987850d136345d9227c6b94c96a04cf4a391bf78"
+ url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.3.1"
flutter:
dependency: "direct main"
description: flutter
@@ -71,35 +79,48 @@ packages:
dependency: transitive
description:
name: http_parser
- url: "https://pub.dartlang.org"
+ sha256: e362d639ba3bc07d5a71faebb98cde68c05bfbcfbbb444b60b6f60bb67719185
+ url: "https://pub.dev"
source: hosted
version: "4.0.0"
matcher:
dependency: transitive
description:
name: matcher
- url: "https://pub.dartlang.org"
+ sha256: "1803e76e6653768d64ed8ff2e1e67bea3ad4b923eb5c56a295c3e634bad5960e"
+ url: "https://pub.dev"
source: hosted
- version: "0.12.10"
+ version: "0.12.16"
+ material_color_utilities:
+ dependency: transitive
+ description:
+ name: material_color_utilities
+ sha256: "9528f2f296073ff54cb9fee677df673ace1218163c3bc7628093e7eed5203d41"
+ url: "https://pub.dev"
+ source: hosted
+ version: "0.5.0"
meta:
dependency: transitive
description:
name: meta
- url: "https://pub.dartlang.org"
+ sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3"
+ url: "https://pub.dev"
source: hosted
- version: "1.3.0"
+ version: "1.9.1"
path:
dependency: transitive
description:
name: path
- url: "https://pub.dartlang.org"
+ sha256: "8829d8a55c13fc0e37127c29fedf290c102f4e40ae94ada574091fe0ff96c917"
+ url: "https://pub.dev"
source: hosted
- version: "1.8.0"
+ version: "1.8.3"
rxdart:
dependency: "direct main"
description:
name: rxdart
- url: "https://pub.dartlang.org"
+ sha256: "7358d9e183dd9002a16c17200186c7af56dd9e210b030853ca669ccd02e3d5d6"
+ url: "https://pub.dev"
source: hosted
version: "0.27.2"
sky_engine:
@@ -111,57 +132,73 @@ packages:
dependency: transitive
description:
name: source_span
- url: "https://pub.dartlang.org"
+ sha256: "53e943d4206a5e30df338fd4c6e7a077e02254531b138a15aec3bd143c1a8b3c"
+ url: "https://pub.dev"
source: hosted
- version: "1.8.1"
+ version: "1.10.0"
stack_trace:
dependency: transitive
description:
name: stack_trace
- url: "https://pub.dartlang.org"
+ sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5
+ url: "https://pub.dev"
source: hosted
- version: "1.10.0"
+ version: "1.11.0"
stream_channel:
dependency: transitive
description:
name: stream_channel
- url: "https://pub.dartlang.org"
+ sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8"
+ url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "2.1.1"
string_scanner:
dependency: transitive
description:
name: string_scanner
- url: "https://pub.dartlang.org"
+ sha256: "556692adab6cfa87322a115640c11f13cb77b3f076ddcc5d6ae3c20242bedcde"
+ url: "https://pub.dev"
source: hosted
- version: "1.1.0"
+ version: "1.2.0"
term_glyph:
dependency: transitive
description:
name: term_glyph
- url: "https://pub.dartlang.org"
+ sha256: a29248a84fbb7c79282b40b8c72a1209db169a2e0542bce341da992fe1bc7e84
+ url: "https://pub.dev"
source: hosted
- version: "1.2.0"
+ version: "1.2.1"
test_api:
dependency: transitive
description:
name: test_api
- url: "https://pub.dartlang.org"
+ sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8"
+ url: "https://pub.dev"
source: hosted
- version: "0.3.0"
+ version: "0.6.0"
typed_data:
dependency: transitive
description:
name: typed_data
- url: "https://pub.dartlang.org"
+ sha256: "53bdf7e979cfbf3e28987552fd72f637e63f3c8724c9e56d9246942dc2fa36ee"
+ url: "https://pub.dev"
source: hosted
version: "1.3.0"
vector_math:
dependency: transitive
description:
name: vector_math
- url: "https://pub.dartlang.org"
+ sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
+ url: "https://pub.dev"
+ source: hosted
+ version: "2.1.4"
+ web:
+ dependency: transitive
+ description:
+ name: web
+ sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10
+ url: "https://pub.dev"
source: hosted
- version: "2.1.0"
+ version: "0.1.4-beta"
sdks:
- dart: ">=2.12.0 <3.0.0"
+ dart: ">=3.1.0-185.0.dev <4.0.0"
diff --git a/pubspec.yaml b/pubspec.yaml
index 77e6135..bbe2ddc 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,17 +1,17 @@
name: google_places_flutter
description: Custom Google places autocomplete widget for Android and iOS both. Use https://pub.dev/packages/google_places_flutter
-version: 2.0.5
+version: 2.0.7
author: Shruti Mahajan
homepage: https://github.com/Shrutimahajan/Google-AutoComplete-TextField-Flutter
environment:
- sdk: '>=2.12.0 <3.0.0'
+ sdk: '>=2.12.0 <4.0.0'
dependencies:
flutter:
sdk: flutter
- dio: ^4.0.0
+ dio: ^5.4.0
rxdart: ^0.27.2