flexDirection: 'row' is not working in FlatList - reactjs

I'm trying to get below output but flexDirection: 'row' is not working properly. Please can anyone explain me how to get below output. Any help is appreciated.
**Required output: **
My output:
My code is:
_renderItem(rowData) {
return(
<View style={{flex: 1, flexDirection: 'row', flexWrap: 'wrap'}}>
<View style={{margin: 2, width: '24%', backgroundColor: '#fff', borderWidth: 1, borderColor: '#aaa'}}>
<TouchableOpacity activeOpacity={0.9} style={{height: 190}}>
<Image source={{uri: rowData.item.images[0].src}} style={{height: '100%', width: '100%'}}/>
</TouchableOpacity>
<View style={{padding: 5}}>
<TouchableOpacity activeOpacity={0.9} style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<View>
<CapitalizedText style={{color: '#666', fontSize: 14}}>{rowData.item.title}</CapitalizedText>
<Text style={{fontSize: 15, color: '#666', justifyContent: 'center', alignItems: 'center'}}>{'₹' + rowData.item.variants[0].price}</Text>
</View>
<Icon size={24} color="#aaa" name="turned-in-not" />
</TouchableOpacity>
<CapitalizedText style={{fontSize: 14, color: '#bbb'}}>Printed Top</CapitalizedText>
</View>
</View>
</View>
);
}
render() {
return(
<View>
{
this.state.product_detail.length <= 0 ?
<ActivityIndicator color = '#bc2b78' size = "large" style={{alignItems: 'center', justifyContent: 'center'}} />
:
<FlatList
keyExtractor = {( item, index ) => index }
data = { this.state.product_detail }
renderItem = {(rowData) => this._renderItem(rowData)}
ListFooterComponent = { this._render_Footer }
/>
}
</View>
);}
Thank you.

Use numColumns property in flatList to align text items of flatList in a row like
let numColumns=5;
<FlatList numColumns={numColumns}/>

Please see this one if is work for you https://snack.expo.io/SywBhpMgW

You only have one child element (another View element) of the view which sets flexDirection to row. FlexDirection only has influence on its direct children.

Related

How to pass numeric input values of components inside flatlist from modal screen to main component screen?

I have a list of items inside a flatlist with numeric inputs of each one of them as follows
My code for the flatlist is as follows:
const BedRoomModal = () => {
return (
<View style={{flex: 1}}>
<ScrollView>
<Text style={Styles.headerText}>Bedroom 1</Text>
<View style={Styles.container}>
<FlatList
data={bedData.BED}
renderItem={renderItem}
keyExtractor={(item) => item.BED_ID}
/>
</View>
</ScrollView>
<TouchableOpacity
onPress={() => BedRoomSave()}
style={{
alignSelf: 'flex-end',
right: 5,
position: 'absolute',
bottom: 10,
}}>
<View
style={{
backgroundColor: '#20B2AA',
alignSelf: 'flex-end',
padding: 10,
}}>
<Text style={{fontSize: 15, fontWeight: 'bold', color: '#fff'}}>
SAVE
</Text>
</View>
</TouchableOpacity>
</View>
);
};
renderItem is as follows:
const renderItem = ({item,index}) => {
return (
<>
<View
style={{
marginBottom: 24,
flexDirection: 'row',
justifyContent: 'space-between',
}}>
<Text style={Styles.checklistTitle}>{item.BED_TITLE}</Text>
<NumericInput
value={bed[index]}
onChange={(value) => bedDataFunction(value,index)}
totalWidth={100}
totalHeight={35}
iconSize={22}
step={1}
valueType="integer"
textColor="#B0228C"
iconStyle={{color: 'black'}}
rightButtonBackgroundColor="#fff"
leftButtonBackgroundColor="#fff"
minValue={0}
/>
</View>
<View style={Styles.itemSeparator}></View>
</>
);
};
bedDataFunction:
const bedDataFunction=(value,id)=>{
console.log('VALUE')
console.log(value)
console.log('ID')
console.log(id)
}
The states that I have used are:
const [bed, setBed] = useState([]);
I get the value inside the console of my onchange function but now I need to take that value and display it on screen? could anyone tell what am I doing wrong here?
Any suggestion would be welcomed, am stuck since long now, hopefully would recieve help, thank you.
Let me know if anything is required for better understanding of the code.

Weird Gap Between Views in React Native

I am new to react naive and am trying to place two views one under the other but when I try doing this there is a big gap between the views as shown below.
This anyway to be able to fix this or do I need to use flatlist?
Here is my code.
render() {
return (
<>
<View style={{ flex: 1, flexDirection: "row", height: 130 }}>
<View style={styles.IconImage}>
<TouchableOpacity
onPress={() =>
Linking.openURL("http://facebook.com/")
}
>
<FontAwesome
name="location-arrow"
size={40}
color={"#E8AA65"}
/>
</TouchableOpacity>
</View>
<View style={{ paddingTop: 50, paddingLeft: 40 }}>
<Text style={{ fontSize: 20 }}>Find Us</Text>
</View>
</View>
<View style={{ flexDirection: "row", height: 130 }}>
<View style={styles.IconImage}>
<TouchableOpacity
onPress={() =>
Linking.openURL("http://facebook.com/")
}
>
<Icon
name={Platform.OS === "ios" ? "ios-settings" : "md-settings"}
size={40}
color={"#E8AA65"}
/>
</TouchableOpacity>
</View>
<View style={{ paddingTop: 50, paddingLeft: 40 }}>
<Text style={{ fontSize: 20 }}>Settings</Text>
</View>
</View>
</>
);
}
const styles = StyleSheet.create({
IconImage: {
paddingTop: 40,
paddingLeft: 40,
},
});
The issue is caused by providing flex:1 in your main view.
Output without flex:1:
The remaining offset is caused by your height together with your padding values.
Demo:
I've created a snack where you can play around with it:
https://snack.expo.io/rkUKpLUUU

When using styles to move buttons, the 'hotspot' remains in place but the buttons moves

When using styles to move buttons where I want them, the touchable area where you can press the button remains in the same place and doesn't follow the button. This makes the button unresponsive and can only be pressed if you find the original location!
I've tried:
using TouchableWithoutFeedback.
Moving the order of the components
Putting all sorts in the style reference.
Here's the render:
render() {
if((this.state.isOn) === true){
return(
<ImageBackground source={require('./assets/water-in-glass.gif')} style={styles.container}>
<Text>Timer:{ms(this.state.time,{verbose: true})}</Text>
<TouchableOpacity
onPressIn={this.onItemMouseDown}
onPressOut={this.onItemMouseUp}
>
<View>
<Image source={require('./assets/MyButton.png')}/>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={this.resetTimer}
>
<View>
<View style={styles.resetbutton}>
<Text style={styles.text}>Reset Timer</Text>
</View>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={this.onSubmit}
>
<View>
<View style={styles.submitbutton}>
<Text style={styles.text}>Done!</Text>
</View>
</View>
</TouchableOpacity>
</ImageBackground>
)
} else if ((this.state.isOn) === false){
return(
<ImageBackground source={require('./assets/water-in-glass.gif')} style={styles.container}>
<Text>Timer:{ms(this.state.time)}</Text>
<TouchableOpacity
onPressIn={this.onItemMouseDown}
onPressOut={this.onItemMouseUp}
>
<View>
<Image source={require('./assets/MyButton.png')}/>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={this.resetTimer}
>
<View>
<View style={styles.resetbutton}>
<Text style={styles.text}>Reset Timer</Text>
</View>
</View>
</TouchableOpacity>
<TouchableOpacity
onPress={this.onSubmit}
>
<View>
<View style={styles.submitbutton}>
<Text style={styles.text}>Done!</Text>
</View>
</View>
</TouchableOpacity>
{this.state.scoreArray.map(function(item,i){
return (i < 5) ? <Text key={i}>{item}</Text> : null}).filter(x=>x)
}
<Text>
{this.state.animalArray.map(function(item,i){
return (i < 5) ? <Text key={i}>{item}</Text> : null}).filter(x=>x)
}
</Text>
</ImageBackground>
here's the styling:
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
},
pissbutton: {
padding: 10,
borderWidth: 3,
borderColor: '#111'
},
resetbutton: {
padding: 10,
borderWidth: 3,
backgroundColor: '#ed1c42'
},
submitbutton: {
marginBottom: 36,
top: 100,
padding: 10,
borderWidth: 3,
backgroundColor: '#42f471'
}
});
I expect when I use styling to move the buttons, they remain responsive, instead of moving, but the hotspot remaining where it is.
Figured it.
The button needed it's own container:
submitbuttoncontainer:{
position: 'absolute',
bottom: 50,
},
submitbutton: {
color: 'white',
fontWeight: 'bold',
fontSize: 12,
justifyContent: 'center',
width: 100,
alignItems: 'center',
}
Wow. That's totally not clear anywhere. I suspect it's my lack of basic knowledge in coding.

React Native FlexLayout: Alignment item right

I have a list of products and want to display the text "ITEM UNIT" at the right end of my infobox. It is however affected by the position of the text above it.
How do I solve this and put "ITEM UNIT" to the right end of the display?
<TouchableOpacity
onPress={() => this.props.onItemClicked(this.props.item)}
style={{ marginRight: 130 }}
>
<View style={styles.itemContent}>
<View>
<FadeIn>
<Image
resizeMode="contain"
style={{
height: 100,
width: 100,
marginTop: 10,
marginLeft: 10
}}
source={{ uri: url }}
/>
</FadeIn>
</View>
<View style={{ justifyContent: "space-around" }}>
<Text style={{ fontSize: 16, fontFamily: "System" }}>
{articleName}
</Text>
<View
style={{
flexDirection: "row",
justifyContent: "space-between"
}}
>
<View style={{ flexDirection: "row" }}>
<Text style={styles.itemPrice}>{originalprice} </Text>
<Text style={styles.itemPriceReduced}>{specialprice}€</Text>
</View>
<View>
<Text>ITEMUNIT</Text>
</View>
</View>
</View>
</View>
</TouchableOpacity>;
I crated a small demo for you. Please check it here:
https://snack.expo.io/#tarikfojnica/layout (Click Tap To Play on the right side)
Here are the code parts you should check:
<TouchableOpacity style={styles.container} onPress={() => this.props.onItemClicked(this.props.item)}>
<View style={styles.itemContent}>
<View style={styles.iconContainer}>
<Image source={Icon} style={styles.icon} />
</View>
<View style={styles.textContainer}>
<Text>This is the title </Text>
<View style={styles.downText}>
<View style={styles.priceText}>
<Text style={{marginRight: 10}}>$99.9</Text>
<Text>$99.9</Text>
</View>
<View style={styles.label}>
<Text>Label</Text>
</View>
</View>
</View>
</View>
</TouchableOpacity>
const styles = StyleSheet.create({
container: {
marginTop: 24,
},
itemContent: {
flexDirection: 'row',
borderBottomWidth: 1,
borderColor: 'e5e5e5'
},
iconContainer: {
padding: 10,
flex: 1,
},
icon: {
width: 40,
heigth: 40
},
textContainer: {
backgroundColor: 'whitesmoke',
flex: 7,
padding: 5
},
downText: {
marginTop: 10,
flexDirection: 'row',
justifyContent: 'space-between'
},
priceText: {
flexDirection: 'row',
},
label: {
textAlign: 'right',
backgroundColor: 'yellow',
padding: 3
}
});
For a reference, here is how it looks like:
PS: I would avoid writing inline styles.

Space between components in React Native styling

I have 6 View components (shown in the picture) , I want to have space between all 6 View components.
My code:
<View style={{flexDirection:'column',flex:6}}>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between'}}>
<View style={{backgroundColor:'red',flex:1}}>
</View>
<View style={{backgroundColor:'blue',flex:1}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between'}}>
<View style={{backgroundColor:'white',flex:1}}>
</View>
<View style={{backgroundColor:'black',flex:1}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between'}}>
<View style={{backgroundColor:'gray',flex:1}}>
</View>
<View style={{backgroundColor:'yellow',flex:1}}>
</View>
</View>
</View>
Try to add padding to the element then and another blank view in each row, padding make space between each item
<View style={{
flexDirection:'column',
flex:1,
}}>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between',padding:10}}>
<View style={{backgroundColor:'red',flex:2,padding:10}}>
</View>
<View style={{flex:0.1}}/>
<View style={{backgroundColor:'blue',flex:2,padding:10}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between',padding:10}}>
<View style={{backgroundColor:'white',flex:2,padding:10}}>
</View>
<View style={{flex:0.1}}/>
<View style={{backgroundColor:'black',flex:2,padding:10}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between',padding:10}}>
<View style={{backgroundColor:'gray',flex:1,padding:10}}>
</View>
<View style={{flex:0.1}}/>
<View style={{backgroundColor:'yellow',flex:1,padding:10}}>
</View>
</View>
You can simply add margins to the elements and it will work fine.
<View style={{flexDirection:'column',flex:6}}>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between', marginBottom: 10}}>
<View style={{backgroundColor:'red',flex:1, marginRight: 5}}>
</View>
<View style={{backgroundColor:'blue',flex:1, marginLeft: 5}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between', marginBottom: 10}}>
<View style={{backgroundColor:'white',flex:1, marginRight: 5}}>
</View>
<View style={{backgroundColor:'black',flex:1, marginLeft: 5}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",justifyContent:'space-between', marginBottom: 10}}>
<View style={{backgroundColor:'gray',flex:1, marginRight: 5}}>
</View>
<View style={{backgroundColor:'yellow',flex:1, marginLeft: 5}}>
</View>
</View>
</View>
As of React Native 0.71.0, you can use the gap property. These child views will have a gap of 10 pixels between each row / column.
<View style={{flexDirection:'column', gap: 10 }}>
<View />
<View />
<View />
<View />
<View />
<View />
</View>
If you are using the map function to render your components, you can try the following code:
// Change to the number of columns in your grid
const numCols = 4;
// Change to the spacing for each item
const spacing = '1.25rem';
// Parent View
<View style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
}}
>
{// List of child views to render
contents.map((content, index) => (
// add a margin of 'spacing' to the bottom of all cards
// will supply a left-margin to all cards in between the gap,
// everytime a card is NOT divisible numCols, add a margin to the left
<View style={{
marginBottom : spacing,
marginLeft: index % numCols !== 0 ? spacing : 0
}}
>
<Card
key={index}
content={content}
/>
</View>
))
}
</View>
I found that using the following code snippet will create an effect similar to gap in css grids.
Give the following styling to the parent container (Block/View).
justifyContent: 'space-around'
OR
justifyContent: 'space-between'
Space-around will put space between all the elements/view/items and also add space to the borders. Same as all elements get the margin.
And the space-between will put the space between all items, without adding space to the borders
All this stuff is explained here beautifully. Here is the link
Try this
const Component = () => {
return (
<View style={styles.container}>
<View style={styles.child}></View>
<View style={styles.child}></View>
</View>
);
};
// Gap you want to achieve
const gap = 8;
const styles = StyleSheet.create({
container: {
flexDirection: "row",
paddingHorizontal: (gap / -2),
},
child: {
marginHorizontal: gap / 2,
},
});
For me, the solution, among using justify-content: 'space-between', was to explicitly give width to the parent view (in my case, width: '100%'), otherwise, 'space-between' didn't do anything.
you have 2 solutions in this case
first, use margin/padding for make air between flex element
and the other way is set justifyContent to 'space-between' || 'space-around'
but you must know about some information to use the best solution in a different case
1- (margin-padding)
in some case (more case), padding better margin
as you know, if we have a box ( means element ), you have two space,
first between content and border [ Inner space ]
second, space between the border and another foreign box element [ outer space ]
if you have an element and you want move element in your style you must use margin, because if you use padding for your element, inner space changed and in many cases, this approach creates some crash in your element,
{{ if you want to use padding you must create one View and wrap all of your element and set the padding for a wrapper for you }}
and if you want to use space-between || space-around, you must know this,
space-between and space-around have one diff
in space-between, space produced between elements and not create space between your element with sides
and space-around set space with elements and with sides
You can give the parent a negative margin in the same direction you use on the children.
const Comp: FC = () => {
return (
<View style={styles.container}>
<View style={styles.item}></View>
<View style={styles.item}></View>
<View style={styles.item}></View>
<View style={styles.item}></View>
</View>
)
}
const styles = StyleSheet.create({
item: {
// Just for visual representation:
borderWidth: 2,
borderColor: '#FF0000',
height: 100,
// Important styles:
marginRight: 15,
flexBasis: '40%',
flexGrow: 1,
},
container: {
// Important styles:
marginRight: -15,
flexDirection: 'row',
flexWrap: 'wrap',
},
});
export default Comp;
<View style={{ flexDirection: "row", flexWrap: "wrap" }}>
{Array(30)
.fill({ name: "product name" })
.map((item, key, arr) => (
<View
key={key}
style={{
height: 200,
paddingTop: 15,
backgroundColor: "skyblue",
...(key % 2 !== 0
? { paddingRight: 15, paddingLeft: 15 }
: { paddingLeft: 15 }),
flexBasis: "50%",
}}
>
<View
style={{
flex: 1,
backgroundColor: variables?.BackgroundLight,
}}
>
<Text style={styles && { ...styles?.text }}>{item.name}</Text>
</View>
</View>
))}
</View>
Try this out. You can better control it using array map
If you want to put some vertical space, without flex, this is simple (just for temporary use)
<View style={{flex:2,flexDirection:"row",flexWrap: 'wrap'}}>
<View style={{backgroundColor:'white',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
<View style={{backgroundColor:'black',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
</View>
<View style={{flex:2,flexDirection:"row",flexWrap: 'wrap'}}>
<View style={{backgroundColor:'gray',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
<View style={{backgroundColor:'yellow',flex:1,marginHorizontal:5,marginVertical:10,}}>
</View>
</View>
You can add the following in your style:
attachcontainer{
flexDirection: 'row',
justifyContent: 'space-between'
}

Resources