Any touch events not trigger when the TextInput is on focus - react-native

I have search input with list of results. I am trying to select the one item from the list. But I am not able to select the item on first press as the input field is on focus. First press is considered to close the keyboard. I want to trigger the touch event on first press with closing the keyboard. My code is given below-
<TextInput
placeholder='Destination'
underlineColorAndroid={'transparent'} style={[styles.input]}
value={this.state.destination}
onChangeText={(text) => this.saveDestination(text)}
/>
<View style={{ backgroundColor: WHITE, marginVertical:
(this.state.predictions.length === 0) ? 0 : 15 }}>
{this.destinationPredictation()}
</View>
destinationPredictation() {
const arr = this.state.predictions;
return arr.map((d, index) => {
return (
<TouchableOpacity
onPress={() => { this.setState({ destination: d.description });
}}
style={[{ flex: 1, paddingHorizontal: 5, paddingTop: 10,
paddingBottom: (index === this.state.predictions.length - 1)
? 10 : 0 }]}
key={d.id}
>
<View style={{ width: (WIDTH - 50), paddingHorizontal: 0,
flexDirection: 'row', alignItems: 'center' }}>
<Icon name='map-marker' size={30} color={REGULAR_OPTION}
style={{ marginHorizontal: 8 }} />
<Text style={[styles.destinationOptions, { flex: 1 }]}>
{d.description}
</Text>
</View>
</TouchableOpacity>
);
});
}

Related

ScrollView will not scroll to the bottom of the contact List

Im creating a contact list.
To do that I have put the contact data into a scroll view.
When the user typed a letter to the search contact and tried to go to the last contact in the list, it won't be shown( it will show a little and it will bounce back up.)
return (
<SafeAreaView>
<ScrollView style={{flexGrow: 1}} bounces={false} >
<View style={{ flex: 1, flexDirection: 'row', borderTopWidth: 0.5, borderTopColor: 'grey'}}>
<View style={{ flex: 1 }}>
<Text onPress={() => setChecked(true)} style={{ fontSize: 20, marginHorizontal: 10 }}>
{item.name + ' '}
</Text>
<Text style={{ fontSize: 17, marginHorizontal: 10, marginTop: 5, color: 'grey' }}>
{item.phoneNumbers && item.phoneNumbers[0] && phone && item.phoneNumbers[0].digits}
</Text>
</View>
<TouchableOpacity
onPress={() => {
onChangeValue(item);
}}
>
<CheckBox
style={{ width: 15, height: 15, paddingTop: 8 }}
right={true}
checked={!!selectedContacts[phoneNumber]}
onPress={() => {
onChangeValue({ item });
}}
/>
</TouchableOpacity>
</View>
</ScrollView>
</SafeAreaView>
);
I did some research and they said to use flexGrow 1 on the scrollView or to make a parent view with flex 1 but none of that was a solution.
How can I show the user the bottom contacts when the user scrolls to the bottom?
please use flex:1 in the scrollView like this.
<View style={{flexDirection: 'column', flex: 1, width: wp(100)}}>
<WaterfallList
data={FinalArray}
bounces={false}
onMomentumScrollBegin={onScrollStart}
onMomentumScrollEnd={onScrollEnd}
heightForItem={item => Dimensions.get('screen').width * 0.6}
numColumns={2}
allLoaded={true}
onLoading={() => console.log('dsd')}
showsHorizontalScrollIndicator={false}
showsVerticalScrollIndicator={false}
contentStyle={{flexGrow: 1}}
style={{
flex: 1,
paddingHorizontal: Dimensions.get('screen').width * 0.03,
backgroundColor: 'transparent',
}}
renderItem={ContactItemServer}
/>
</View>

1st index hidden Item not hidding when swiping the another element - swiperFlatList React native

as you can see in the image, I have implemented adding Text inputs dynamically with the button press, everything is working perfectly only the 1st text input hidden item (Remove Button) not hiding when swiping the other text inputs.
const initialState = {
col1: '',
key: 0,
};
const [inputField, setInputField] = useState<Values[]>([initialState]);
<SwipeListView
data={inputField}
renderItem={data => renderItem(data)}
renderHiddenItem={data => renderHiddenItem(data)}
leftOpenValue={55}
rightOpenValue={-100}
disableRightSwipe={true}
ListHeaderComponent={
<View style={[styles.headingContainer]}>
<Text style={[styles.headingText]}>{Props.inputHeading}</Text>
</View>
}
ListFooterComponent={
<View style={styles.buttonContainer}>
<TouchableOpacity
style={styles.addBtn}
activeOpacity={0.7}
onPress={onPressAddBtn}>
<Text style={styles.BtnText}>Add</Text>
</TouchableOpacity>
<TouchableOpacity style={styles.submitBtn} activeOpacity={0.7}>
<Text style={styles.BtnText}>Submit</Text>
</TouchableOpacity>
</View>
}
style={{height: Dimensions.get('screen').height / 1.3}}
/>
const renderItem = (data: any) => {
return (
<TouchableHighlight key={data.item.key}>
<TextInput
placeholder="Hello"
onChangeText={e => handleChange(data.item.key, 'col1', e)}
value={data.item.col1}
style={[styles.textInput, Props.textInputStyle]}
// {...Props.textInputProps}
/>
</TouchableHighlight>
);
};
const renderHiddenItem = (rowData: any) => {
return (
<View
style={{
justifyContent: 'flex-end',
flexDirection: 'row',
alignItems: 'center',
}}>
<TouchableOpacity
activeOpacity={0.7}
style={{
backgroundColor: 'red',
justifyContent: 'center',
flexDirection: 'row',
width: 90,
height: 45,
alignItems: 'center',
borderRadius: 5,
}}>
<Text style={{color: 'white'}}>Remove</Text>
</TouchableOpacity>
</View>
);
};
but other all element's swipe is working as expected only the first element is not working as expected
found solution by adding keyExtractor={item => item.key.toString()} to swiper flatlist.

Render variable number of items n per row (2 in my example) in react native without using Flatlist

I have a case in which I am using a ScrollView.
I receive n number of paymentMediums from api which I need to render 2 per row.
With Flatlist this is just easy and I have implemented as
<FlatList
scrollEnabled={false}
numColumns={2}
data={this.state.paymentMediums}
keyExtractor={item => String(item.paymentMasterIdentifier)}
renderItem={({ item, index }) => (
<TouchableOpacity
key={item.paymentMasterIdentifier}
onPress={() => this.setState({ selectedPaymentMedium: item.paymentMasterIdentifier, selectedPaymentMediumName: item.paymentMethodName })}
style={[styles.checkboxView, { marginBottom: 10, width: (width - 32) / 2, alignSelf: 'center' }]}>
<View style={{ borderRadius: 10, borderWidth: 3, borderColor: this.state.selectedPaymentMedium == item.paymentMasterIdentifier ? MyColors.COLOR_ACCENT : '#F1D3C3' }}>
<Image
resizeMode="contain"
style={styles.paymentImage}
source={{ uri: item.imageUrl }}
/>
</View>
<Text style={{ color: this.state.selectedPaymentMedium == item.paymentMasterIdentifier ? MyColors.COLOR_ACCENT : '#7A7A7A' }}>{item.paymentMethodName}</Text>
</TouchableOpacity>
)}
/>
However this gives the obvious warning of virtualized list should never be nested inside plain scrollview. So, I need to render them in a normal way without Flatlists.
I tried it as, {this.renderPaymentMediums()} inside render() where
renderPaymentMediums() {
let paymentMediums = this.state.paymentMediums;
console.log('incoming', paymentMediums.length)
for (let index = 0; index < paymentMediums.length; index += 2) {
return (<View style={{}}>
{ this.renderEachPaymentMediums(paymentMediums[index], paymentMediums[index + 1] ? paymentMediums[index + 1] : null)
}
</View>)
}
}
renderEachPaymentMediums = (item, item2 = null) => {
return (
<View style={{ flexDirection: 'row', flex: 1, marginBottom: 10 }}>
<View style={{ alignItems: 'center' }}>
<TouchableOpacity
key={item.paymentMasterIdentifier}
onPress={() => this.setState({ selectedPaymentMedium: item.paymentMasterIdentifier, selectedPaymentMediumName: item.paymentMethodName })}
style={[styles.checkboxView, { width: (width - 32) / 2, }]}>
<View style={{ padding: 3, borderRadius: 10, borderWidth: 3, borderColor: this.state.selectedPaymentMedium == item.paymentMasterIdentifier ? MyColors.COLOR_ACCENT : '#F1D3C3' }}>
<Image
resizeMode="contain"
style={styles.paymentImage}
source={{ uri: item.imageUrl }}
/>
</View>
<Text style={{ color: this.state.selectedPaymentMedium == item.paymentMasterIdentifier ? MyColors.COLOR_ACCENT : '#7A7A7A' }}>{item.paymentMethodName}</Text>
</TouchableOpacity>
</View>
<View style={{ alignItems: 'center' }}>
{item2 !== null && (
<TouchableOpacity
key={item2.paymentMasterIdentifier}
onPress={() => this.setState({ selectedPaymentMedium: item2.paymentMasterIdentifier, selectedPaymentMediumName: item2.paymentMethodName })}
style={[styles.checkboxView, { width: (width - 32) / 2 }]}>
<View style={{ padding: 3, borderRadius: 10, borderWidth: 3, borderColor: this.state.selectedPaymentMedium == item2.paymentMasterIdentifier ? MyColors.COLOR_ACCENT : '#F1D3C3' }}>
<Image
resizeMode="contain"
style={styles.paymentImage}
source={{ uri: item2.imageUrl }}
/>
</View>
<Text style={{ color: this.state.selectedPaymentMedium == item2.paymentMasterIdentifier ? MyColors.COLOR_ACCENT : '#7A7A7A' }}>{item2.paymentMethodName}</Text>
</TouchableOpacity>
)}
</View>
</View>
)
}
This does not work since it returns from the first iteration of loop with the return.
So, how do I make this work.
Also, I want to ask if using using Flatlists inside ScrollView takes a toll on the performance. I have disabled the scroll of the inside Flatlist so that 2 scrolling behaviours dont overlap and hence I dont get the warning.But the warning persists. Does this step do any good??

First show the profile clicked then swipe between profiles react native

Hi how can I first show the user that I've clicked on and then display a swiper ? I can't find a logic for that. I have a list of users and when I click on one, it should open a new component where we will find more infos about that user. Then I want to swipe between the list of users on the same component of the description ?
Here are my user profile component and the flatlist :
render () {
var colorConnected;
if (this.props.navigation.getParam('Statut') === "ON") {
colorConnected = "#1fbc26";
}
else if (this.props.navigation.getParam('Statut') === "OFF") {
colorConnected = "#ff0303";
}
else {
colorConnected = "#ffd200";
}
return (
<Swiper showsPagination={false}>
{this.state.items.map((item, key) => {
return (
<ScrollView style = {styles.view_container}>
<View style={styles.photo}>
<ImageBackground source={{uri:this.props.navigation.getParam('Photo')}} style={{ width: '100%', height: '100%' }}>
<View style={styles.photo_content}>
<LinearGradient colors={['transparent', 'rgba(0,0,0,0.5)']} style={{ position: 'absolute', left: 0, right: 0, bottom: 0, height: 80 }} />
<View style={{ flexDirection: 'row', alignItems: 'center' }}>
<View>
<Text style={{ fontSize: 40, color:'white' }}>{this.props.navigation.getParam('Age')}</Text>
</View>
<View style={{ marginRight: 7, marginLeft: 7, backgroundColor: '#ffffff', width: 1, height: 39 }}></View>
<View style={{ flexDirection: 'column', flex:1 }}>
<View style={{ flexDirection: 'row' }}>
<View style={[styles.bulle_presence, { backgroundColor: colorConnected } ]}></View>
<Text style={{ fontSize: 18, fontWeight: '600', color:'white' }}>{this.props.navigation.getParam('Pseudo')}</Text>
</View>
<View style={{ flexDirection: 'row', justifyContent: 'space-between'}}>
<Text style={{ fontSize: 15, color:'white' }}>{this.props.navigation.getParam('Distance')}</Text>
<Text style={{ fontSize: 15, color:'white'}}>{this.props.navigation.getParam('Genre')}</Text>
</View>
</View>
</View>
</View>
</ImageBackgroud>
</View>
</ScrollView>
)
})}
</Swiper>
)}
}
render() {
GLOBAL.data = this.state.dataSource;
//console.log(GLOBAL.data);
return (
<SafeAreaView style={{ flex:1 }}>
<View style={styles.main_container}>
<FlatList style={styles.flatList}
data={this.state.dataSource}
extraData = {this.state}
keyExtractor={(item, index) => item.MembreId}
renderItem={(item) => <UserItem user={item} displayDetailForUser={this._displayDetailForUser} />}
numColumns={numColumns}
refreshing={this.state.refreshing}
onRefresh={this.handleRefresh} />
</View>
</SafeAreaView>
)
}
With this code, I'm only able to swipe on the user where I've clicked. The others user are not showing.
You can open a modal then use a carousel like react-native-snap-carousel in full screen mode to generate your use case

React Native progress fill screen

In my app, I am trying to display a progress bar using the ActivityIndicator upon a click event on a TouchableHightlight element. The problem is that I would like to have my progress bar fill up the whole screen (even filling up the spaces occupied by the navigation bar). Or if it is possible, a progress bar that takes up all the touch events on the screen while it is being displayed.
render()
{
let progress;
if (this.state.isLoading) {
progress = <ActivityIndicator style={[progressStyle.container, progressStyle.horizontal]}/>
}
return (
<ScrollView>
<View style={{
zIndex: 1,
flex: 1,
alignItems: 'center',
justifyContent: "flex-start",
}}>
<View style={{
flex: 1,
alignItems: 'flex-end',
paddingTop: 5,
paddingHorizontal: 10,
marginBottom: 10
}}>
<View style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginTop: 8,
marginBottom: 8
}}>
<Text style={labelStyle}>Name: </Text>
<TextInput
style={ textInputStyle }
value={ this.state.name }
onChangeText={(text) => {
this.setState({
name: text
});
}} />
</View>
<View style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginBottom: 8
}}>
<Text style={labelStyle}>Start Date: </Text>
<DatePicker
style={ datePickerStyle }
date={this.state.startDate}
mode="date"
placeholder="select start date"
format="YYYY-MM-DD"
confirmBtnText="Confirm"
cancelBtnText="Cancel"
onDateChange={(date) => {
this.setState({startDate: date});
}} />
</View>
<View style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginBottom: 8
}}>
<Text style={labelStyle}>End Date: </Text>
<DatePicker
style={ datePickerStyle }
date={this.state.endDate}
mode="date"
placeholder="select end date"
format="YYYY-MM-DD"
confirmBtnText="Confirm"
cancelBtnText="Cancel"
onDateChange={(date) => {
this.setState({endDate: date});
}} />
</View>
<View style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginBottom: 8
}}>
<Text style={labelStyle}>Max members: </Text>
<TextInput
style={ textInputStyle }
keyboardType="numeric"
value={ this.state.maxMembers }
onChangeText={(text) => {
this.setState({
maxMembers: text
});
}} />
</View>
<View style={{
flex: 1,
flexDirection: 'row',
alignItems: 'center',
marginBottom: 8
}}>
<Text style={labelStyle}>Available Until: </Text>
<DatePicker
style={ datePickerStyle }
date={this.state.availabilityDeadLine}
mode="date"
placeholder="select date til when this space is available"
format="YYYY-MM-DD"
confirmBtnText="Confirm"
cancelBtnText="Cancel"
customStyles={{
placeholderText:{
textAlign: 'center'
}
}}
onDateChange={(date) => {
this.setState({availabilityDeadLine: date});
}} />
</View>
</View>
<ListOption
text="Create Room"
style={{
backgroundColor: (this.state.name!='' && this.state.startDate!=''
&& this.state.endDate!='' && this.state.maxMembers!=''
&& this.state.availabilityDeadLine!='')? Colors.tintColor : '#232323',
textColor: Colors.tintTextColor,
}}
onClick={
() => {
this.state.isLoading=true; this.setState({});
var tDate = new Date();
tDate.setHours(0,0,0,0);
if(this.state.name != '' && this.state.startDate != '' &&
this.state.endDate != '' && this.state.maxMembers != '' &&
this.state.availabilityDeadLine != ''){
if(new Date(this.state.startDate) > new Date(this.state.endDate)){
Alert.alert("start date cannot be after end date");
} else if(new Date(this.state.endDate) < tDate) {
Alert.alert("end date cannot be before today");
} else if(new Date(this.state.availabilityDeadLine) < tDate) {
Alert.alert("space has to be available at least up until today");
} else {
// this.state.isLoading = false;
// this.props.navigation.goBack();
}
}
}
} />
</View>
{progress}
</ScrollView>
);
}
const progressStyle = StyleSheet.create({
container: {
zIndex: 4,
justifyContent: 'center',
backgroundColor: '#565656',
position: 'absolute',
top:0, left: 0, right: 0, bottom: 0
},
horizontal: {
flexDirection: 'row',
justifyContent: 'space-around',
padding: 10
}
})
I've tried giving contentContainerStyle={{flex:1}} to my ScrollView but I don't want my ListOption element to take up all the leftover space on screen and look fat. Right now, my ActivityIndicator takes up the whole of ScrollView, which is not taking up the whole screen.
So, will there be any way for me to give different flex abilities to the children of ScrollView element such that I can have my ActivityIndicator take up the whole screen while my View takes up as much as its contents?
You would need to wrap it inside a modal if you want it to fill the entire and set {width: "100%", height: "100%"}