I am quite new with React native and I'm not sure how to implement this design:
Grid layout
I have 20px horizontal padding around the whole app and I want to size these squares so they would form like a large rectangle with these gaps in between. I don't really want to hardcode these sizes.
I managed to get the design without any gaps by dividing the total width by 3 and then giving the big square 2/3 and the small squares 1/3. But how can I do this with the gaps ?
const themedStyles = useThemedStyles();
const width = Dimensions.get('window').width - 40;
return (
<View style={styles.container}>
<View style={styles.textContainer}>
<ThemedText style={themedStyles.subHeader}>Trending</ThemedText>
<ThemedText style={[themedStyles.accentText, {fontWeight: 'bold'}]}>
See all
</ThemedText>
</View>
<View style={styles.cardContainer}>
<View
style={{
width: (width / 3) * 2,
height: (width / 3) * 2,
backgroundColor: 'white',
borderWidth: 2,
}}></View>
<View>
<View
style={{
width: width / 3,
height: width / 3,
backgroundColor: 'white',
borderWidth: 2,
}}></View>
<View
style={{
width: width / 3,
height: width / 3,
backgroundColor: 'white',
borderWidth: 2,
}}></View>
</View>
</View>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-between',
},
textContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
},
cardContainer: {
flexDirection: 'row',
},
});
See below Code maybe it will help you:
import React from 'react';
import { View, Image, StyleSheet,Dimensions } from 'react-native';
const width = Dimensions.get('window').width - 40;
const styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'space-between',
padding:20
},
textContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
flex:1,
backGroundColor:'red'
},
cardContainer: {
flexDirection: 'row',
justifyContent: 'space-between',
},
});
const DisplayAnImage = () => {
return (
<View style={styles.container}>
<View style={styles.cardContainer}>
<View
style={{
width: (width / 3) * 2,
height: (width / 3) * 2,
backgroundColor: 'white',
borderWidth: 2,
}}></View>
<View style={{justifyContent: 'space-between'}}>
<View
style={{
width: width / 3.5,
height: width / 3.5,
backgroundColor: 'white',
borderWidth: 2,
}}></View>
<View
style={{
width: width / 3.5,
height: width / 3.5,
backgroundColor: 'white',
borderWidth: 2,
}}></View>
</View>
</View>
</View>
);
}
export default DisplayAnImage;
Related
i have 12 card view on homescreen
im using Flat list to render the 12 cards
I have 2 columns set so 2 cards in the view
i would like to tweak it so after every 2 cards 1 card be full width then the next 2 cards next to each other and the third is full width and so on
here is my code
<FlatList
data={ this.state.GridListItems }
keyExtractor={(item) => item.id.toString()}
renderItem={ ({item, index}) =>
<TouchableOpacity style={{width: (index + 1) % 3 === 0 ? '108%' : '54%', height: '110%', justifyContent:'center', overflow: "hidden",
flex:1,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
backgroundColor: '#231F20',
borderRadius: 5,
shadowColor: '#000',
shadowOffset: { width: 5, height: 5 },
shadowOpacity: 0.8,
shadowRadius: 5,
elevation: 6,
padding: 5,}}
onPress={() => this.props.navigation.navigate('ProfileScreen', { height: "6'2", category: item.key })}>
<ImageBackground
source={{ uri: item.img }}
style={{width: '108%', height: '110%', justifyContent:'center'}} >
<View style={{position: 'absolute', top: 0, left: 0, right: 0, bottom: 0, justifyContent: 'center', alignItems: 'center'}}>
<Text style={styles.GridViewTextLayout} > {item.key} </Text>
</View>
</ImageBackground>
</TouchableOpacity>
}
numColumns={2}
initialNumToRender={6}
/>
i want it to render 2 cards (each card 50% of screen) and every third card (100% of the screen) for the 12 element
you can try this. so, on every third card, it should display the full width.
const styles = {
GridViewContainer: {
justifyContent:'center',
overflow: "hidden",
flex:1,
justifyContent: 'center',
alignItems: 'center',
margin: 5,
backgroundColor: '#231F20',
borderRadius: 5,
shadowColor: '#000',
shadowOffset: { width: 5, height: 5 },
shadowOpacity: 0.8,
shadowRadius: 5,
elevation: 6,
padding: 5,
}
}
<FlatList
data={this.state.GridListItems}
keyExtractor={(item) => item.id.toString()}
renderItem={({item, index}) =>
<TouchableOpacity
style={styles.GridViewContainer}
onPress={() => this.props.navigation.navigate('ProfileScreen', { height: "6'2", category: item.key })}
>
<ImageBackground
source={{ uri: item.img }}
style={{
width: (index + 1) % 3 === 0 ? '216%' : '108%',
height: '110%',
justifyContent: 'center',
}}
>
<View
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
bottom: 0,
justifyContent: 'center',
alignItems: 'center'
}}
>
<Text style={styles.GridViewTextLayout}> {item.key} </Text>
</View>
</ImageBackground>
</TouchableOpacity>
}
numColumns={2}
initialNumToRender={6}
/>
edited to reflect the styling for GridViewContainer
I am learning react-native and the flexbox layouts don't seem to be consistent. In the code snippet below all I am trying to do is have a divider in the middle of the screen but it always align to the left:
<View style={styles.row}>
<View
style={{
flex: 0.8,
justifyContent:'center',
borderColor: '#1abc9c',
borderWidth: 1
}}
/>
</View>
</View>
let styles = StyleSheet.create({
row: {
flexDirection: 'row',
marginHorizontal: 6,
marginVertical: 6,
},
});
Can somebody please let me know what I am doing wrong here?
Try this:
<View
style={{
flex: 1, // << look at this // Occupy the entire container
flexDirection: "row",
marginHorizontal: 6,
marginVertical: 6,
justifyContent: "center" // center the children horizontally -
//since flexDirection: 'row'
}}
>
<View
style={{
flex: 0.5,
justifyContent: "center",
borderColor: "#1abc9c",
borderWidth: 1
}}
/>
</View>
I have tried using both KeyboardAvoidingView and ScrollView to prevent my content from being squished (pushed up) when the keyboard is present. I have tried using padding, height, and position for my behavior but nothing is working. Can someone please tell me how I can force my content to ignore the keyboard and not get pushed up??
return (
<View style={{height: '100%', backgroundColor: '#D6D6D6', position: 'relative'}}>
<View style={styles.wrapper}>
<View style={{height:'100%', borderRadius: 7}}>
<View style={styles.container}>
<ScrollView style={{borderRadius: 7}}
horizontal
showsHorizontalScrollIndicator={false}
scrollEventThrottle={10}
pagingEnabled
onScroll={
Animated.event(
[{nativeEvent: {contentOffset: {x: this.animVal}}}]
)
}
>
{imageArray}
</ScrollView>
<View style={styles.listViewContainer}>
<TouchableOpacity style={styles.listView} onPress={() => Actions.pop()}>
<View style={{flex: 1, flexBasis: 22}}>{listIcon}</View>
<View style={{flex: 2, flexBasis: 57}}><Text style={{color: '#fff'}}>List View</Text></View>
</TouchableOpacity>
</View>
<View style={styles.circleContainer}>
{circleArray}
</View>
</View>
<View style={styles.productsSection}>
<Text style={styles.title}>{prodDesc}</Text>
<Text style={styles.desc}>{prodBrand}</Text>
<Text style={styles.desc}>Item: {prodId || ''}</Text>
<Text style={[styles.desc, {marginBottom: 15}]}>Category: {prodCat}</Text>
<Table borderStyle={{borderWidth: 0}}>
<Rows data={rows}/>
</Table>
</View>
<View style={styles.bodyFooter}>
<QuantityCounter style={{width: '100%', display: 'block', marginRight: 20}} data={{productId: prodId}} />
</View>
</View>
</View>
<View style={styles.footer}>
<View style={styles.cartContainer}>
{cartIcon}
<Text style={{color: '#3A3A3A', fontSize: 14}}>18 items</Text>
</View>
<TouchableOpacity style={styles.viewCartButtonContainer} onPress={() => this.cartRedirect() }>
<Text style={{color: '#fff', fontSize: 15, marginTop: '5%'}}>View Cart</Text>
</TouchableOpacity>
</View>
<Header/>
</View >
);
here are my main styles for this:
var styles = StyleSheet.create({
wrapper: {
backgroundColor: '#E6E6E6',
marginVertical: 15,
marginHorizontal: 10,
borderRadius: 7,
elevation: 3,
maxHeight: '80%',
flexShrink: 1,
zIndex: 0,
marginTop: 75
},
container: {
flex: 1.7,
justifyContent: 'space-between',
alignItems: 'center',
height: '50%',
borderRadius: 7
},
footer: {
justifyContent:'space-between',
alignItems: 'center',
height: '10%',
backgroundColor: '#E6E6E6',
paddingVertical: 15,
paddingHorizontal: 17,
flexDirection: 'row',
borderStyle: 'solid',
borderTopColor: '#8E8E93',
borderTopWidth: 1
},
cartContainer: {
flexDirection: 'row',
width: '35%'
},
viewCartButtonContainer: {
backgroundColor: '#356FAF',
height: '90%',
width: '45%',
padding: 20,
alignItems: 'center',
justifyContent: 'center',
borderRadius: 3
},
bodyFooter: {
backgroundColor: '#F6F6F6',
justifyContent: 'center',
flex: 0.45,
borderTopColor: '#D6D6D6',
borderTopWidth: 1,
borderStyle: 'solid',
borderBottomRightRadius: 7,
borderBottomLeftRadius: 7
},
circleContainer: {
position: 'absolute',
zIndex: 2,
bottom: 10,
left: 10,
flexDirection: 'row',
},
listViewContainer: {
position: 'absolute',
zIndex: 10,
top: 0,
right: 0,
justifyContent: 'center'
},
listView: {
display: 'flex',
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
borderTopRightRadius: 3,
backgroundColor: '#000',
paddingVertical: 5,
paddingHorizontal: 10
},
What it looks like without the keyboard:
What it looks like with the keyboard:
Handling View behavior when toggling a keyboard can be a tricky thing in React Native. There are multiple possible solutions to questions like this, but in this case the solution was this:
Instead of using style={{height:'100%'}} on your components that get pushed up, try using Dimensions:
import {Dimensions} from 'react-native';
const { height } = Dimensions.get('window');
and specify style={{ height }} in the right components.
Another thing that might be worth a try if someone else stumbles on this question:
React Native for Android has some default settings defined in the Android manifest. If you are not using Expo (or CRNA), you can change the behavior of the keyboard in AndroidManifest.xml by changing the windowSoftInputMode rule.
Try changing android:windowSoftInputMode="adjustResize" to android:windowSoftInputMode="adjustPan" or to android:windowSoftInputMode="adjustNothing". You can try to play around with some other options (See here) if this doesn't give you the desired effect.
You should use try behavior as "none" for android and if you don't want to getting small, you can set android:windowSoftInputMode="adjustPan" in manifest file.
and if still face any error checkout react-native-keyboard-aware-scrollview
here on npm.
I went through a similar problem and solved it by changing
android:windowSoftInputMode="adjustPanā€¯
In android manifest.
Also clean and rebuild. This might work
remove the position absolute it will works just fine trust me
for some cases if you want keep defualt manifest
you can move your elements inside a Scrollview it may help.
issue solved for me in this way
Hi I'm new in react native. I would like to ask how to fixed the position of these three colors, because every time i tried to click the search text input and the keyboard goes up those three colors will also goes up. I tried position: 'fixed' but it didnt work.
Screenshot
Here is also the code:
render(){
return(
<View style={{flex: 1}}>
<View style={{flex: 3, backgroundColor: '#E1F1FE'}}>
<View style={styles.form}>
<TextInput
style={styles.input}
placeholder = "Search"
returnKeyType="go"
underlineColorAndroid={'rgba(0,0,0,0)'}
/>
<Icon name="search" size={20} color="#900" style={styles.label} />
</View>
</View>
<View style={{flex: 1, backgroundColor: '#77D3F8'}}>
</View>
<View style={{flex: 1, backgroundColor: '#AEEAF2'}}>
</View>
<View style={{flex: 1, backgroundColor: '#39CFDE'}}>
</View>
</View>
);
}
and the styles
import {StyleSheet} from 'react-native';
module.exports = StyleSheet.create({
navBar: {
backgroundColor: '#EAEAEC',
},
title: {
color: '#rgba(0, 0, 0, 0.65)',
},
buttonText: {
color: '#rgba(0, 0, 0, 0.45)',
},
style3:{
fontSize: 35,
color: '#fff',
padding: 10,
alignContent:'center',
justifyContent: 'center',
},
style2: {
flexDirection: 'row',
alignContent: 'center',
alignItems: 'center',
flex:1
},
buttonstyle: {
flex: 1
},
form:{
flexDirection: 'row',
borderBottomWidth:1,
borderColor: '#00BBD1',
marginTop:80,
marginRight: 40,
marginLeft: 40,
alignContent: 'center',
alignItems: 'center',
},
input: {
height: 40,
borderWidth: 0,
flex: 1
},
label:{
alignContent:'center',
justifyContent: 'center',
marginRight: 10,
color: '#00BBD1'
},
});
Thank you in advance :)
It will not going to be stick to position when keyboard activated. You may need to use keyboardavoidingview or another package like react-native-keyboard-aware-scroll-view So design may not disturb when keyboard activated.
I treat it like an exercise. There are 28 components. I want to have maximum 4 rows of components, where in each row there is maximum 7 components and minimum 1 depending on screen size (28 rows then). Could you help me how to accomplish this? I know I can use flex-wrap: wrap style but I want to have maximum 7 components in a row. Help me please with this as Im new to React Native and Flexbox.
<View style={styles.container}>
<View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'red'}}></View>
<View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'green'}}></View>
<View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'yellow'}}></View>
<View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'brown'}}></View>
<View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'blue'}}></View>
<View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'red'}}></View>
<View style={{ flex: 1, margin: 2, height: 40, backgroundColor: 'green'}}></View>
.
.
.
</View>
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
justifyContent: 'center',
},
});
This problem can't be solved in bootstrap way (column, row stuff etc). Flexbox lacks the capability to make specific number of components appear in a row depending upon screen size.
You need to use ListView such that ListView renders 7 components in a row. ListView's renderRow function iterates over an array and displays content of each index of that array in a row. So, at each index you need to define json containing 7 attributes and return all these attributes in the form of an array to make them appear in a row.
In my project, I had to show 3 or less images in a row (as displayed in Media section of attached image) so I used the above mentioned approach to achieve this. Please find below my code. This might help you.
constructor() {
// data saved in state
this.state = {
mediaFiles: [{image: "image link"},
{image: "image link"},
{image: "image link"},
{image: "image link"},
{image: "image link"},
{image: "image link"},
{image: "image link"},
{image: "image link"},
],
dataSource: ds.cloneWithRows([])
}
}
componentDidMount() {
var temp = [];
//to ensure three images appear in a row
for (var index = 0; index < this.state.mediaFiles.length; index = index + 3) {
temp.push({
image1: this.state.mediaFiles[index].image,
image2: (index + 1) < this.state.mediaFiles.length ? this.state.mediaFiles[index + 1].image : null,
image3: (index + 2) < this.state.mediaFiles.length ? this.state.mediaFiles[index + 2].image : null
});
}
this.setState({
dataSource: this.state.dataSource
.cloneWithRows(temp)
});
}
renderMediaThumbnails(rowData) {
var mediaThumbnails = [],
key = 0;
for (var attribute in rowData) {
if (rowData[attribute]) {
mediaThumbnails.push(
<View key={key++} style={Styles.imageWrapper}>
<Image style={Styles.media} source={{uri: rowData[attribute]}} />
</View>)
}
}
return mediaThumbnails
}
renderRow(rowData) {
return (
<View style={Styles.mediaWrapper}>
{this.renderMediaThumbnails(rowData)}
</View>
);
}
render() {
return (
<View style={Styles.statusAndMedia}>
<ListView
dataSource={this.state.dataSource}
renderRow={this.renderRow.bind(this)} />
</View>
);
}
Following are the styles:
mediaWrapper: {
flex: 1,
flexDirection: "row",
justifyContent: "space-around",
marginVertical: 3,
},
imageWrapper: {
borderWidth: 2,
borderColor: "#AE8B8C"
},
media: {
height: 50,
width: 85,
resizeMode: "stretch"
}
Ok I think I found the solution. I set a width of a parent View to the with of screen or to the 294 (width of 7 elements + margins) if the screen size is larger. Maybe hardcoding it to 294 would be enough but Im not able to check it on small screen now.
var width = Dimensions.get('window').width;
class Schedule extends React.Component {
render() {
return (
<View style={styles.container}>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'red'}}></View>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'green'}}></View>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'yellow'}}></View>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'brown'}}></View>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'blue'}}></View>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'red'}}></View>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'green'}}></View>
<View style={{ margin: 1, width: 40, height: 40, backgroundColor: 'red'}}></View>
</View>
)
}
};
export default Schedule;
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
width: width > 294 ? 294 : width
},
});
ListView is deprecated now , you can use SectionList or FlatList instead.