如何在React Native中使用Google Autocomplete Search API和React Native Maps来获取用户位置?

Today we will be making an Ola/Uber like address component where you can fetch a users location in three ways :

今天,我们将制作类似于Ola / Uber的地址组件,您可以通过以下三种方式获取用户位置:

  1. By using Google-AutoComplete Search API

    通过使用Google-AutoComplete搜索API

  2. By Dragging a google map around a centred marker

    通过在中心标记周围拖动Google地图

  3. By text input entered by the user

    通过用户输入的文字

Our aim is to have a screen which looks like this :

我们的目标是拥有一个看起来像这样的屏幕:

Image for post
Google Auto Complete Search
Google自动完成搜索

If you are looking for a quick solution this will be really helpful and I hope you achieve more than what I am offering you using the process I followed.

如果您正在寻找一种快速的解决方案,这将非常有帮助,并且希望您能按照我所遵循的过程实现比我提供的更多的目标。

Wear your anti glare glasses and let’s begin !

戴上防眩眼镜,让我们开始吧!

Step 1 : Install react-native-maps

第1步:安装react-native-maps

npm install react-native-maps

npm安装react-native-maps

The version I used at the time of publishing was 0.26.1. If you wish to install the same version so that there is no version mismatch try :

我在发布时使用的版本是0.26.1。 如果您希望安装相同的版本,以防止版本不匹配,请尝试:

npm install react-native-maps@0.26.1

npm安装react-native-maps@0.26.1

Step 2 : Install react-native-google-places-autocomplete

第2步:安装react-native-google-places-autocomplete

npm install react-native-google-places-autocomplete

npm install react-native-google-places-autocomplete

The version I used is 1.4.0.

我使用的版本是1.4.0。

Now in your project folder create a file : AddAddress.tsx ( You can go ahead with any name or extension as per the guidelines in your project. You might have to format the code at some points if you are using Javascript. )

现在在您的项目文件夹中创建一个文件:AddAddress.tsx(您可以按照项目中的准则继续使用任何名称或扩展名。如果使用Javascript,则可能必须在某些时候格式化代码。)

AddAddress.tsx

AddAddress.tsx

import React from "react";import {View,StyleSheet} from "react-native";import MapView from "react-native-maps";import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";export default class LocationPickerDemo extends React.Component<any, any> {
render(){
(<View>
</View>);
}
}const styles = StyleSheet.create({});

This is how your initial file should look like. As you can see we have imported both our libraries react-native-maps and react-native-google-places-autocomplete already to use their functionalities. MapView will help us to render the map and GooglePlacesAutocomplete will give us the search bar at top as you can see in the image. We have created a custom stylesheet as well in our component which we will be populating soon.

这就是您的初始文件的外观。 如您所见,我们已经导入了我们的库react-native-maps和react-native-google-places-autocomplete来使用它们的功能。 MapView将帮助我们渲染地图,而GooglePlacesAutocomplete将使我们在图片中可以看到顶部的搜索栏。 我们还在组件中创建了一个自定义样式表,我们将很快填充它。

Next we are going to implement the map on the screen for starting off with the Google API integrations in your react native app :

接下来,我们将在屏幕上实现地图,以从您的react native应用程序中的Google API集成开始:

AddAddress.tsx

AddAddress.tsx

import React from "react";import {View,StyleSheet} from "react-native";import MapView from "react-native-maps";import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";const latitudeDelta = 0.025;
const longitudeDelta = 0.025;export default class LocationPickerDemo extends React.Component<any, any> {state = {
region: {
latitudeDelta,
longitudeDelta,
latitude: 12.840575,
longitude: 77.651787,
}
}render(){
<View style={styles.map}>
<MapView
style={styles.map}
initialRegion={this.state.region}
/>
</View>}
}const styles = StyleSheet.create({
map:{
flex:1
},
});

Next we will keep our fetch Address API ready and integrate our GOOGLE API KEY with the search API.

接下来,我们将准备好获取地址API并将其GOOGLE API KEY与搜索API集成在一起。

AddAddress.tsx

AddAddress.tsx

import React from "react";import {View,StyleSheet} from "react-native";import MapView from "react-native-maps";import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";const latitudeDelta = 0.025;
const longitudeDelta = 0.025;export default class LocationPickerDemo extends React.Component<any, any> {state = {
region: {
latitudeDelta,
longitudeDelta,
latitude: 12.840575,
longitude: 77.651787,
}
}getAddress(){
//function to get address using current lat and lngfetch("https://maps.googleapis.com/maps/api/geocode/json?address=" + this.state.region.latitude+"," +this.state.region.longitude +"&key=" + <YOUR_GOOGLE_API_KEY>).then((response) => response.json()).then((responseJson) => {
console.log("ADDRESS GEOCODE is BACK!! => " +
JSON.stringify(responseJson));
this.setState(
{ address: JSON.stringify(responseJson.results[0].formatted_address)
.replace(/"/g, "")
});
});
}render(){
<View style={styles.map}>
<MapView
style={styles.map}
initialRegion={this.state.region}
/>
</View>}
}const styles = StyleSheet.create({
map:{
flex:1
},
});

The getAddress() function returns the value of an address that we receive as a result of the geocode api call we have made inside the function passing your key and coordinates. Next we will introduce the TextInput address in our component.

getAddress()函数返回由于在函数内部进行的地理编码api调用而收到的地址的值,并传递了键和坐标。 接下来,我们将在组件中引入TextInput地址。

import React from "react";import {View,    Image,TouchableOpacity,TextInput,KeyboardAvoidingView,Text} from "react-native";import { Icon } from 'react-native-elements';import MapView from "react-native-maps";import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";const latitudeDelta = 0.025;
const longitudeDelta = 0.025;export default class AddressPicker extends React.Component<any, any> {state = {
region: {
latitudeDelta,
longitudeDelta,
latitude: 12.840575,
longitude: 77.651787,
},
address:""
}getAddress(){
//function to get address using current lat and lngfetch("https://maps.googleapis.com/maps/api/geocode/json?address=" + this.state.region.latitude+"," +this.state.region.longitude +"&key=" + <YOUR_GOOGLE_API_KEY>).then((response) => response.json()).then((responseJson) => {
console.log("ADDRESS GEOCODE is BACK!! => " +
JSON.stringify(responseJson));
this.setState(
{ address: JSON.stringify(responseJson.results[0].formatted_address)
.replace(/"/g, "")
});
});
}render(){
<View style={styles.map}>
<MapView
style={styles.map}
initialRegion={this.state.region}
/>//Added a custom marker at the center of screen
<View style={styles.markerFixed}>
<Image
style={styles.marker}
source={require("../../assets/marker.png")}/>
</View>//Created A Footer Panel to show/enter address
<KeyboardAvoidingView style={styles.footer}>
<View style={{ flexDirection: "row", margin: 10 }}>
<Icon name="ios-home"
size={24}
color="#000000"
type="ionicon"
style={{
padding: 10,
}}
/>
<Text style={styles.addressText}>Address</Text>
</View>
<TextInput
multiline={true}
clearButtonMode="while-editing"
style={{
marginBottom: 5,
width: "90%",
minHeight: 70,
alignSelf: "center",
borderColor: "lightgrey",
borderWidth: 1.5,
fontSize: 12,
borderRadius: 5,
flex: 0.5,
alignContent: "flex-start",
textAlignVertical: "top",
fontFamily: "Calibri",
}}
onChangeText={(text) =>this.setState({ address: text })}
value={this.state.address}
/>
<TouchableOpacity
onPress={() => {}}
style={{
width: "30%",
alignSelf: "center",
alignItems: "center",
backgroundColor: "blue",
borderRadius: 16.5,
shadowColor: "rgba(0,0,0, .4)", // IOS
shadowOffset: { height: 1, width: 1 }, // IOS
shadowOpacity: 1, // IOS
shadowRadius: 1, //IOS
elevation: 2, // Android
}}>
<Text
style={{
color: "white"
fontFamily: "Calibri",
fontSize: 12,
paddingVertical: 4,
}}>
SAVE
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
}
}const styles = StyleSheet.create({
map:{
flex:1
},
markerFixed: {
left: "50%",
marginLeft: -24,
marginTop: -48,
position: "absolute",
top: "50%",
},
addressText: {
color: "black",
margin: 3,
fontFamily: "Calibri",
},
footer: {
backgroundColor: "white",
bottom: 0,
position: "absolute",
width: "100%",
height: "30%",
},
});

Now if you run your app you will be able to see the Map with a marker in the center of the screen and the address field at the bottom of the screen. Now lets implement the GoogleAutoComplete feature and finish off rest of the functionalities.

现在,如果您运行应用程序,则可以在屏幕中央看到带有标记的Map,在屏幕底部可以看到地址字段。 现在,让我们实现GoogleAutoComplete功能并完成其余功能。

Note : You will have to edit the below file as per your requirements and install the missing components/remove add necessary tags.

注意:您将必须根据需要编辑以下文件,并安装缺少的组件/删除添加必要的标签。

import React from "react";import {Image,StyleSheet,Text,View,TextInput,TouchableOpacity,
KeyboardAvoidingView} from "react-native";import MapView from "react-native-maps";import { GooglePlacesAutocomplete } from "react-native-google-places-autocomplete";const latitudeDelta = 0.025;
const longitudeDelta = 0.025;export default class LocationPickerDemo extends React.Component<any, any> {searchText: any;
mapView: any;
state = {
region: {
latitudeDelta,
longitudeDelta,
latitude: 12.840575,
longitude: 77.651787,
},
listViewDisplayed: true,
address: "",
showAddress: false,
search: "",
currentLat: "",
currentLng: "",
forceRefresh: 0,
};goToInitialLocation = (region) => {
let initialRegion = Object.assign({}, region);
initialRegion["latitudeDelta"] = 0.005;
initialRegion["longitudeDelta"] = 0.005;
this.mapView.animateToRegion(initialRegion, 2000);
};onRegionChange = (region) => {
this.setState({
region: region,
forceRefresh: Math.floor(Math.random() * 100),
},
this.getCurrentAddress//callback
);
};componentWillMount() {
this.getCurrentAddress();
}getAddress({
fetch("https://maps.googleapis.com/maps/api/geocode/json? address=" + this.state.region.latitude+"," +this.state.region.longitude +"&key=" + <YOUR_GOOGLE_API_KEY>).then((response) => response.json()).then((responseJson) => {
console.log("ADDRESS GEOCODE is BACK!! => " +
JSON.stringify(responseJson));
this.setState(
{ address: JSON.stringify(responseJson.results[0].formatted_address)
.replace(/"/g, "")
});
});
}render() {
const { region } = this.state;

return (
<View style={styles.map}>
<MapView
ref={(ref) => (this.mapView = ref)}
onMapReady={() =>
this.goToInitialLocation(this.state.region)}
style={styles.map}
initialRegion={this.state.region}
onRegionChangeComplete={this.onRegionChange}
/> <View style={styles.panel}>
<View style={[styles.panelHeader,
this.state.listViewDisplayed? styles.panelFill:styles.panel,]}>. <GooglePlacesAutocomplete
currentLocation={false}
enableHighAccuracyLocation={true}
ref={(c) => (this.searchText = c)}
placeholder="Search for a location"
minLength={2} // minimum length of text to search
autoFocus={false}
returnKeyType={"search"}
listViewDisplayed={this.state.listViewDisplayed}
fetchDetails={true}
renderDescription={(row) => row.description}
enablePoweredByContainer={false}
listUnderlayColor="lightgrey"
onPress={(data, details) => {
this.setState({
listViewDisplayed: false,
address: data.description,
currentLat: details.geometry.location.lat,
currentLng: details.geometry.location.lng,
region: {
latitudeDelta,
longitudeDelta,
latitude: details.geometry.location.lat,
longitude:details.geometry.location.lng,
},
});
this.searchText.setAddressText("");
this.goToInitialLocation(this.state.region);}}
textInputProps={{
onChangeText: (text) => {
console.log(text);
this.setState({listViewDisplayed: true});
},
}}
getDefaultValue={() => {
return ""; // text input default value
}}
query={{
key: "<YOUR_API_KEY>",
language: "en", // language of the results
components: "country:ind",
}}
styles={{
description: {
fontFamily: "Calibri",
color: "black",
fontSize: 12,
},
predefinedPlacesDescription: {
color: "black",
},
listView: {
position: "absolute",
marginTop: 44,
backgroundColor:"white",
borderBottomEndRadius: 15,
elevation:2,},}}
nearbyPlacesAPI="GooglePlacesSearch"
GooglePlacesSearchQuery={{
rankby: "distance",
types: "building",}}
filterReverseGeocodingByTypes={[
"locality","administrative_area_level_3",]}
debounce={200}/></View></View><View style={styles.markerFixed}>
<Image
style={styles.marker}
source={require("../../assets/pinmarker.png")}/>
</View><KeyboardAvoidingView style={styles.footer}>
<View style={{ flexDirection: "row", margin: 10 }}>
<Icon name="ios-home"
size={24}
color="#DC2B6B"
type="ionicon"
style={{
padding: 10,
}}
/>
<Text style={styles.addressText}>Address</Text>
</View>
<TextInput
multiline={true}
clearButtonMode="while-editing"
style={{
marginBottom: 5,
width: "90%",
minHeight: 70,
alignSelf: "center",
borderColor: "lightgrey",
borderWidth: 1.5,
fontSize: 12,
borderRadius: 5,
flex: 0.5,
alignContent: "flex-start",
textAlignVertical: "top",
fontFamily: "Calibri",
}}
onChangeText={(text) =>this.setState({ address: text })}
value={this.state.address}
/>
<TouchableOpacity
onPress={() => {}}
style={{
width: "30%",
alignSelf: "center",
alignItems: "center",
backgroundColor: "lightgreen",
borderRadius: 16.5,
shadowColor: "rgba(0,0,0, .4)", // IOS
shadowOffset: { height: 1, width: 1 }, // IOS
shadowOpacity: 1, // IOS
shadowRadius: 1, //IOS
elevation: 2, // Android
}}>
<Text
style={{
color: "white"
fontFamily: "Calibri",
fontSize: 12,
paddingVertical: 4,
}}>
SAVE
</Text>
</TouchableOpacity>
</KeyboardAvoidingView>
</View>
}
}const styles = StyleSheet.create({
map:{
flex:1
},
markerFixed: {
left: "50%",
marginLeft: -24,
marginTop: -48,
position: "absolute",
top: "50%",
},
addressText: {
color: "black",
margin: 3,
fontFamily: "Calibri",
},
footer: {
backgroundColor: "white",
bottom: 0,
position: "absolute",
width: "100%",
height: "30%",
},
panelFill: {
position: "absolute",
top: 0,
alignSelf: "stretch",
right: 0,
left: 0,
},
panel: {
position: "absolute",
top: 0,
alignSelf: "stretch",
right: 0,
left: 0,
flex: 1,
},
panelHeader: {
//add custom header
},
});

Thats It ! We are done !

而已 ! 我们完了 !

We are now able to drag our map around and set the address in the text input box, change our address using Google Auto complete search while the map drags to the location selected and enter address using the text input manually.

现在,我们可以在地图上四处拖动并在文本输入框中设置地址,在地图拖动到所选位置的同时使用Google自动完成搜索更改地址,并使用文本输入手动输入地址。

Let me know if you face any issues while implementing it and feedbacks are welcome as this is my first attempt.

让我知道您在实施它时是否遇到任何问题,欢迎您提供反馈,因为这是我的第一次尝试。

Happy Coding ! Hakuna Matata !

编码愉快! Mat田Mat!

翻译自: https://medium.com/debugger-off/how-to-use-google-autocomplete-api-s-and-react-native-maps-in-react-native-to-fetch-user-location-20d3f65af48b

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值