我第一次使用 Flutter 来构建移动应用程序,但我发现没有办法在文本编辑组件中实现自动完成谷歌地点。我的目标是在用户输入位置时获得一种列表视图,就像我们在 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)
});
});
}
}
正如我们从地理定位器中看到的,我们可以根据我们输入的地址检索某些位置(因此我们可以从那里获取结果),但我没有找到一种明智的方法来实现文本编辑建议部分
我和你有同样的问题。实际上 google 自动完成可以通过基本的 HTTP API 请求来完成。我已经创建了一些关于它的文章,名为“你自己的 - 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
函数可以定义为异步函数来调用Google提供的Google Places Autocomplete
标准API请求
https://maps.googleapis.com/maps/api/place/autocomplete/json?
请参阅此链接以更好地了解 Google 地点自动完成功能。
不要忘记添加会话令牌,以便您的账单安全:)
— 标识自动完成的随机字符串 用于计费目的的会话。如果这个参数被省略 自动完成请求,该请求独立计费。请参阅 详细价格表。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');
}
}
您必须在 Widget 的首字母处声明
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
欲了解更多说明,请查看以下链接。
Google 为 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!)),
);}
请使用 onChanged 而不是监听器。