React Native: Scrollview won't scroll with row direction and flexWrap - javascript

in my react-native app I have a scrollview where my list items are row wrapped (flexDirection:'row',flexWrap:'wrap'), however because of this my scrollview won't scroll for some reason...
My scrollview:
<View style={{flex:1}}>
<ScrollView vertical={true} contentContainerStyle={{ borderWidth:1,flex:1,flexDirection:'row',flexWrap:'wrap',alignItems: 'flex-start'}}>
{root.userStore.passionOptions.map((item,index) => {return (
<Text key={item} onPress={ ()=>{ Alert.alert('kaka') } } style={{ fontSize:18,padding:5,paddingLeft:10,paddingRight:10,color:'rgb(125,125,125)',borderRadius:35,borderWidth:1,borderColor:'rgba(0,0,0,0.1)',margin:5 }}>{item}</Text>
)
})}
</ScrollView>
</View>
EDIT:I tried removing flexWrap and flexDirection property and it won't scroll neither

It works for me like this i made the scrollView the outter component
<ScrollView>
<View
lightColor="#eee"
style={{ paddingHorizontal: 7, paddingVertical: 5 }}
>
{children}
</View>
</ScrollView>

Reason not to work:
Your flexDirection is conflicting with ScrollDirection.
Solution:
So to avoid conflict you can have another View inside ScrollView and do the flexWrap logic
<ScrollView>
<View
style={{
borderWidth:1,
flex:1,
flexDirection:'row',
flexWrap:'wrap',
alignItems: 'flex-start'
}}
>
...Your Views over here...
</View>
</ScrollView>

Related

React Native flatlist takes a while to update items

So i am currently making a messaging application and this needs to be able to live messages, I am using a flat list to display these items and everytime i append an item to the messageFetch it takes ages for the flat list to load, (at any time there could be 100's to 1000's of items in the list). How can I speed this up? Also the components are of diffrent sizes.
flatlist component:
<View style={styles.container}>
<View style={styles.topBar} focusable>
<Text style={{ fontFamily: "Roboto-Regular", fontSize: 17, color: "white" }}>{name}</Text>
</View>
<View style={styles.mainChat} focusable>
<View style={[styles.loading, { display: loadedFinished ? "none" : "flex" }]}>
<ActivityIndicator style={[styles.loading, { display: loadedFinished ? "none" : "flex" }]} />
</View>
<FlatList
inverted
ref={list}
data={messageFetch.reverse()}
renderItem={Message}
keyExtractor={(item) => item.index}
/>
</View>
</View>
loadedFinished only runs once and stops at about 3 seconds.
Message Component:
function Message({ item }) {
if (item.embed.type != undefined) {
return <Text>hello<Text>
}
return (
<View style={[mesgStyles.mainMessage, { flexDirection: item.original ? "row-reverse" : "row" }]}>
<Image style={mesgStyles.userPfp} resizeMode="contain" source={{ uri: item.pfp }}></Image>
<View style={mesgStyles.spacer} />
<View style={mesgStyles.messageBody}>
<Text style={mesgStyles.mainText}>{item.text}</Text>
</View>
</View>
);
}
Any help would be greatly appreciated. Thanks

React-Native FlatList takes more space than needed [duplicate]

I have a FlatList component, consisting of 3 sections:
<View style={{ flex: 1 }}>
<FlatList
ListHeaderComponent={Comp1}
ListFooterComponent={<Comp2 style={{ flexGrow: 1, justifyContent: 'flex-end' }}/>}
renderItem={Comp3}
contentContainerStyle={{ flexGrow: 1 }}
/>
</View>
By default, the ListFooterComponent will render right after the ListHeaderComponent, if data.length is 0.
I need to render it at the bottom all the time.
One workaround I've found so far is to provide an empty view for ListEmptyComponent. In this case, it looks fine, until I add at least one item - then it sticks to the top again.
Is it possible to attach ListFooterComponent to the bottom by default?
The blue color is the FlatList, the red color - ListFooterComponent
If it needs to be on the bottom of the screen at all times, you can wrap the separate parts in a ScrollView
render() {
return (
<ScrollView style={{flex: 1}}>
<Comp1/>
<FlatList
style={{flex: 1}}
renderItem={Comp3}
/>
<Comp2/>
</ScrollView>
);
}
Before rederising your View, a good idea is to set your height according to the size of the screen. Something like:
const {height} = Dimensions.get ('window');
The View would look like this:
<View style = {{flex: 1, height: height}}>
Add position: 'relative' to the View:
<View style = {{flex: 1, height: height, position: 'relative'}}>
Then add ListFooterComponentStyle to FlatList:
ListFooterComponentStyle = {{
backgroundColor: '# ccc',
position: 'absolute,
width: '100%',
bottom: 0
}}
Show a complete example function component:
const {height} = Dimensions.get('window'); //capture the screen size
return (
<SafeAreaView style={{flex:1,height:height,backgroundColor:'#f5f5f5', position:'relative'}}>
<FlatList
data = {YOUR_DATA}
renderItem = {renderItem}
keyExtractor = {item => item.idItem}
numColumns = {2} // Divide list items into 2 columns (optional)
onEndReached = {LOAD_MORE_DATA}
onEndReachedThreshold = {0.1} //0.1 = 10%
ListFooterComponent = {YOUR_COMPONENT_FOOTER}
ListFooterComponentStyle={{
backgroundColor:'#ccc',
position:'absolute',
width:'100%',
bottom:0
}}
/>
</SafeAreaView>
)
add flexGrow: 1 to contentContainerStyle of Flatlist
add flexGrow: 1 to ListFooterComponentStyle of Flatlist
add flex: 1 and justifyContent: "flex-end" to View of container used in ListFooterComponent
<FlatList
contentContainerStyle = {{flexGrow: 1}}
listFooterComponentStyle = {{flexGrow: 1}}
listFooterComponent = {()=>(
<View style={{
flex:1,
justifyContent: "flex-end"
}}>
...Component you want at bottom
</View>
)}
/>

Map array image elements horizontally

I'm trying to map images in an array horizontally, but they're being mapped vertically no matter what I do.
const numberOfRows = Math.ceil(images.length / 3);
const result = Array(numberOfRows)
.fill()
.map((_, rowIndex) => (
<View key={rowIndex}>
{images
.slice(rowIndex * 5, rowIndex * 5 + 5)
.map((image, imageIndex) => (
<TouchableOpacity
key={imageIndex}
onPress={() => alert("image pressed!")}
>
<Image
source={{
uri:
"https://miro.medium.com/max/814/1*Cxm5opOziPF5iavnDSYHLg.png"
}}
style={{ width: 100, height: 100 }}
/>
</TouchableOpacity>
))}
</View>
));
What am I doing wrong here?
The standard flex-direction of a View is vertical. By adding flexDirection: 'row' to your parent View, you can overwrite this behavior.
Code
<View key={rowIndex} style={{flexDirection: 'row'}}>
...
</View>
Working Snack:
https://snack.expo.io/rygY2Vb3H
By default react-native View flex-direction was column. So to align vertically add flexDirection: 'row' to view :
<View key={rowIndex} style={{flex: 1, flexDirection: 'row', flexWrap: 'wrap'}}>
... // your image map code
</View>
You just need to add flexDirection to your View.
<View key={rowIndex} style={{flex: 1, flexDirection: 'row'}}>
...
</View>
You can read more about flexDirection from here.

Keyboard blocking textinput with Scrollview and KeyboardAvoidingView in react native

I am using RN 0.55.4 + Expo
I tried to use KeyboardAvoidingView to my form but it doesnt change anything with or without KeyboardAvoidingView, its still blocking my form. I am using
tcomb-form
This is my current code
return (
<View style={styles.container}>
<KeyboardAvoidingView>
<ScrollView>
<View>
<Header/>
<View style={styles.inputs}>
<LoginForm
formType={formType}
form={this.props.auth.form}
value={this.state.value}
onChange={self.onChange.bind(self)}/>
{passwordCheckbox}
</View>
<FormButton/>
<View >
<View style={styles.forgotContainer}>
{leftMessage}
{rightMessage}
</View>
</View>
</View>
</ScrollView>
</KeyboardAvoidingView>
</View>
)
This is the style
var styles = StyleSheet.create({
container: {
flexDirection: 'column',
flex: 1
},
inputs: {
marginTop: 10,
marginBottom: 10,
marginLeft: 10,
marginRight: 10
},
forgotContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
marginTop: 10,
marginLeft: 10,
marginRight: 10
}
})
This is the display
I also tried https://github.com/APSL/react-native-keyboard-aware-scroll-view library but still same result, keyboard is blocking the view / form.
Anyone know whats wrong?
For iOS you should set the "behavior" parameter of the KeyboardAvoidingView to "padding" :
<KeyboardAvoidingView behavior="padding">
Refering to react-native documentation :
Note: Android and iOS both interact with this prop differently.
Android may behave better when given no behavior prop at all, whereas
iOS is the opposite.
A working example on iOS and Android :
<KeyboardAvoidingView behavior={Platform.OS == "ios" ? "padding" : null}>
It also happened to me... ScrollView and FlatList can work it out by setting a dynamic height depending on your data to FlatList. eg:
<ScrollView>
<FlatList style={{height: dataArr.length * YourInputHeight}}
...
/>
</ScrollView>

Trying to create two columns in react-native

I am trying to create a two column grid using flex. One column will be used to display a word or phrase and the second column will be used to translate the first column. Here is a link: http://imgur.com/nZGo8pb to give you a visual idea on what I am trying to achieve.
I am unable to get two columns side by side. I am only able to have my words appear on top of each other. This is best attempt. A huge failure.http://imgur.com/a/ICApr
My code is:
nent} from 'react';
import { Text, View,StyleSheet,Image,TextInput,ListView} from 'react-native';
class AddWords extends Component{
state = {words:['iku','konkai','kaikan'],
word:'',
EnglishWords:['go','this time','next time']
}
renderList(tasks){
return(
tasks.map((task) =>{
return(
<View key={task} style={styles.item}>
<Text>
{task}
</Text>
<Text>
</Text>
</View>
)
})
)
}
renderEnglishWords(english){
return(
english.map((english) =>{
return(
<View key={english} style={styles.item2}>
<Text>
{english}
</Text>
<Text>
</Text>
</View>
)
})
)
}
addWord(){
let words = this.state.words.concat([this.state.word]);
this.setState({words})
}
render(){
return(
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={(word) => {
this.setState({word})
}}
onEndEditing={()=>this.addWord()}
/>
<View style={styles.wordContainer}>
{this.renderList(this.state.words)}
{this.renderEnglishWords(this.state.EnglishWords)}
<View style={styles.item2}>
</View>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
container:{
flex:1,
borderWidth:3,
borderColor:'green',
flexDirection:'column',
paddingTop:10
},
wordContainer:{
flexDirection: 'column',
borderColor:'blue',
borderWidth:2
},
input:{
height:60,
borderWidth:1,
borderRadius:5,
borderColor:'black',
textAlign:'center',
margin:10,
paddingTop:20,
paddingBottom:10
},
item:{
borderColor:'red',
borderWidth:2
},
item2:{
borderColor:'black',
borderWidth:2,
flexDirection:'column',
}
})
export default AddWords;
Any help will be greatly appreciated.
Thanks.
You need to wrap both inner containers in another <View> with the following style:
<View style={styles.container}>
<TextInput
style={styles.input}
onChangeText={(word) => {
this.setState({ word })
}}
onEndEditing={this.addWord}
/>
<View style={{ flexDirection: 'row', flex: 1 }}>
<View style={styles.wordContainer}>
...
</View>
<View style={styles.item2}>
...
</View>
</View>
</View>
It's because the flexDirection in styles.wordContainer is set to 'column', it should be set to 'row'.
Check out this link on flex-direction examples.

Categories

Resources