Я сейчас использую react-native-google-places-autocomplete
в Formik
и react-native-keyboard-aware-scroll-view
. Но когда пользователь нажимает на первый элемент автоматически предложенного listView
, это приводит к очень непредсказуемым результатам. Либо
1) не отвечает,
2) listView
закрывается и адрес не выбирается, либо
3) listView
остается открытым, но отправляет форму, даже если кнопка отправки формы не была нажата.
Как ни странно, когда нажимаются любые другие элементы в списке, кроме первого, это приводит к желаемым результатам.
const onFocusAddressAutoComplete = () => {
Animated.timing(googlePlacesAnimation, {
toValue: 1,
duration: 300,
}).start(() => {
setFocus(true)
})
}
const onBlurAddressAutoComplete = () => {
setFocus(false)
Animated.timing(googlePlacesAnimation, {
toValue: 0,
duration: 300,
}).start()
}
const animatedPictureHeightStyle = {
height: pictureHeightInterpolation,
width: pictureHeightInterpolation,
opacity: googlePlacesOpacityInterpolation,
}
const animatedHeightStyle = {
height: introHeightInterpolation,
opacity: googlePlacesOpacityInterpolation,
}
const animatedButtonHeightStyle = {
height: buttonHeightInterpolation,
opacity: googlePlacesOpacityInterpolation,
}
const onFocusProps = () => {
onFocusAddressAutoComplete()
}
const onBlurProps = (param, callback) => {
callback(param)
onBlurAddressAutoComplete()
}
const submitHandler = input => {
//submit logic
}
return (
<KeyboardAwareScrollView
contentContainerStyle={styles.container}
showsVerticalScrollIndicator={false}
keyboardShouldPersistTaps={'always'}
keyboardDismissMode={'on-drag'}
>
<Formik
initialValues={{ address: '', introduction: '' }}
onSubmit={submitHandler}
validationSchema={yup.object().shape({
address: yup
.string()
.min(5)
.max(30)
.required(),
introduction: yup
.string()
.max(300),
})}
>
{({ values, handleChange, errors, setFieldTouched, touched, isValid, handleSubmit }) => (
<FlatList
data={[
{
id: 1,
menu:
<View style={styles.title}>
<Text style={styles.titleText}>Sign up</Text>
<TouchableHighlight
onPress={() => navigation.navigate('Posting')}
underlayColor={'rgba(0, 0, 0, 0)'}
activeOpacity={0.2}
>
<Icon
name="x"
size={moderateScale(30)}
color={"black"}
/>
</TouchableHighlight>
</View>
},
{
id: 2,
menu:
<View style={styles.fieldset}>
<Text style={styles.addressLegend}>
<Text style={{ color: '#FF5D4E' }}>* </Text>
Your location for rental pickups
</Text>
<View style={{ flex: 1, justifyContent: 'flex-start' }}>
<GooglePlacesInput
value={values.address}
onBlur={() => onBlurProps('address', setFieldTouched)}
onChangeTextFromFormik={handleChange('address')}
onFocus={onFocusProps}
focus={focus}
/>
</View>
{
touched.address && errors.address &&
<Text style={{ fontSize: 10, color: 'red' }}>{errors.address}</Text>
}
</View>
},
{
id: 3,
menu:
<Animated.View style={[styles.buttonContainer, animatedButtonHeightStyle]} >
<TouchableHighlight
disabled={!isValid || loading || called || signupLoading}
onPress={handleSubmit}
style={[styles.button, isSigninPressed && { borderColor: '#EAC0C0' }]}
underlayColor={'#FF5D4E'}
activeOpacity={0.2}
onShowUnderlay={() => signinPressed(true)}
onHideUnderlay={() => signinPressed(false)}
>
<Text style={[styles.buttonText, isSigninPressed && { color: 'white' }]}>Submit</Text>
</TouchableHighlight>
</Animated.View>
}
]}
renderItem={renderItem}
scrollEnabled={false}
keyExtractor={item => item.id.toString()}
keyboardShouldPersistTaps={'always'}
/>
)
}
</Formik >
</KeyboardAwareScrollView>
)
И компонент GooglePlacesIput
:
export default GooglePlacesInput = ({
onFocus,
onBlur,
onChangeTextFromFormik,
value,
addressRef,
focus,
}) => {
return (
<GooglePlacesAutocomplete
ref={addressRef}
placeholder='Search'
minLength={1} // minimum length of text to search
autoFocus={false}
returnKeyType={'search'} // Can be left out for default return key https://facebook.github.io/react-native/docs/textinput.html#returnkeytype
keyboardAppearance={'light'} // Can be left out for default keyboardAppearance https://facebook.github.io/react-native/docs/textinput.html#keyboardappearance
listViewDisplayed={focus} // true/false/undefined
fetchDetails={true}
textContentType={'fullStreetAddress'}
autoCapitalize={'words'}
selectionColor={'red'}
clearButtonMode={'always'}
autoCompleteType={'street-address'}
// blurOnSubmit={false}
renderDescription={row => row.description} // custom description render
onPress={(data, details = null) => { // 'details' is provided when fetchDetails = true
// const lat = JSON.stringify(details.geometry.location.lat)
// const lng = JSON.stringify(details.geometry.location.lng)
const { description, types } = data && data
const address = {
lat: details.geometry.location.lat,
lng: details.geometry.location.lng,
location: description,
addressType: types,
}
onChangeTextFromFormik(address)
}}
textInputProps={{
onChangeText: (text) => { },
onFocus,
onBlur,
}}
value={value}
getDefaultValue={() => ''}
query={{
// available options: https://developers.google.com/places/web-service/autocomplete
key: googleAPIKeyForAutocomplete,
language: 'en', // language of the results
// region: "CA",
// types: '(cities)' // default: 'geocode'
types: '', // default: 'geocode'
location: '43.70011, -79.4163',
radius: '100000', //100 km
components: 'country:ca',
strictbounds: true,
}}
styles={{
container: {
width: '100%',
},
listView: {
position: 'absolute',
top: 70,
left: 10,
right: 10,
backgroundColor: 'transparent',
borderRadius: 5,
flex: 1,
elevation: 3,
zIndex: 1000,
margin: 0,
},
textInputContainer: {
backgroundColor: 'transparent',
marginTop: 0,
width: '100%',
padding: 0,
borderTopWidth: 0,
borderBottomWidth: 0,
},
textInput: {
backgroundColor: '#F9F5F4',
borderRadius: 50,
width: "100%",
height: height / 15,
marginLeft: 0,
marginRight: 0,
marginTop: 0,
paddingLeft: 30,
fontSize: 15,
},
description: {
// color: '#ac879a',
fontWeight: '300',
},
predefinedPlacesDescription: {
color: '#1faadb'
}
}}
currentLocation={true} // Will add a 'Current location' button at the top of the predefined places list
currentLocationLabel="Current location"
nearbyPlacesAPI='GooglePlacesSearch' // Which API to use: GoogleReverseGeocoding or GooglePlacesSearch
GoogleReverseGeocodingQuery={{
// available options for GoogleReverseGeocoding API : https://developers.google.com/maps/documentation/geocoding/intro
}}
GooglePlacesSearchQuery={{
// available options for GooglePlacesSearch API : https://developers.google.com/places/web-service/search
rankby: 'distance',
type: 'food'
}}
GooglePlacesDetailsQuery={{ fields: 'geometry', }}
// GooglePlacesDetailsQuery={{
// // available options for GooglePlacesDetails API : https://developers.google.com/places/web-service/details
// fields: 'formatted_address',
// }}
filterReverseGeocodingByTypes={['locality', 'administrative_area_level_3']} // filter the reverse geocoding results by types - ['locality', 'administrative_area_level_3'] if you want to display only cities
predefinedPlaces={[]}
enablePoweredByContainer={false}
debounce={200} // debounce the requests in ms. Set to 0 to remove debounce. By default 0ms.
renderLeftButton={() => { }}
renderRightButton={() => { }}
/>
)
}