I want to center a button horizontally, this is my code:
return (
<View style={styles.root}>
<View style={styles.container}>
<SafeAreaView style={HEADER}>
<SliderBox
style={{ height: '100%' }}
currentImageEmitter={index => setCurrentSliderNumber(index)}
images={data.images}>
</SliderBox>
</SafeAreaView>
{currentSliderNumber == data.images.length - 1 ? <View style={styles.item}>
<Button
style={styles.getStartedButton}
appearance="ghost"
status="control"
onPress={onGetStartedPressed}
>
Get Started
</Button>
</View> : null}
</View>
</View>
)
and this is my styling:
const styles = StyleSheet.create({
forgotPasswordButton: {
paddingHorizontal: 0,
},
root: {
flex: 1,
height: '100%',
backgroundColor: '#fff'
},
container: {
borderColor: 'rgba(0,0,0,0.2)',
},
getStartedButton: {
marginVertical: 12,
backgroundColor: 'red'
},
item: {
borderColor: 'rgba(0,0,0,0.2)',
position: 'absolute',
top: '80%',
left: '50%'
}, text: {
position: 'absolute',
top: '30%',
left: '10%'
}
})
I also tried to add alingnItems:center to root:
root: {
flex: 1,
height: '100%',
backgroundColor: '#fff',
alignItems: 'center',
justifyContent: 'center',
}
But the result is not the one expected:
Try changing the item style object to this:
item: {
borderColor: 'rgba(0,0,0,0.2)',
position: 'absolute',
top: '80%',
left:0,
width:"100%",
alignItems:"center",
justifyContent:"center"
},
Do not use position until it's necessary you should use flex properties.
return (
<View style={styles.root}>
<View style={styles.container}>
<SafeAreaView style={HEADER}>
<SliderBox
style={{ height: '100%' }}
currentImageEmitter={index => setCurrentSliderNumber(index)}
images={data.images}>
</SliderBox>
</SafeAreaView>
{currentSliderNumber == data.images.length - 1 ? <View style={styles.item}>
<Button
style={styles.getStartedButton}
appearance="ghost"
status="control"
onPress={onGetStartedPressed}
>
Get Started
</Button>
</View> : null}
</View>
</View>
)
Styles
const styles = StyleSheet.create({
forgotPasswordButton: {
paddingHorizontal: 0,
},
root: {
flex: 1,
height: '100%',
backgroundColor: '#fff'
},
container: {
borderColor: 'rgba(0,0,0,0.2)',
flexGrow:1,
justifyContent: "space-between"
},
getStartedButton: {
marginVertical: 12,
backgroundColor: 'red',
alignSelf:"center",
flexGrow:2,
},
item: {
borderColor: 'rgba(0,0,0,0.2)',
flexGrow:1,
justifyContent:"center",
alignItem:"center",
}, text: {
}
})
Check out the layout docs
Related
I'm using a flatlist with rowNumber={4} and I want to display some elements with a Width-max.
But I got this result :
As you can see some elements protrude on the left side. How can I make it fit automatically ?
Expected result :
There is my code :
<SafeAreaView>
<View
style={{
height: "100%",
maxWidth: "100%",
right: "10%",
}}
>
<FlatList
style={{width: "120%"}}
data={brands}
numColumns={4}
keyExtractor={(_, item) => item}
renderItem={({item}) => (
<View style={styles.card} key={item["id"]}>
<TouchableOpacity
onPress={() => {
var index = brandId.indexOf(item["id"]);
if (index > -1) {
brandId.splice(index, 1);
cpt = cpt - 1;
} else {
brandId.push(item["id"]);
cpt = cpt + 1;
}
console.log("ici ! ", cpt);
console.log("Il existe deja bro", brandId);
}}
>
<Text style={styles.text}>{item["name"]}</Text>
</TouchableOpacity>
</View>
)}
/>
</View>
</SafeAreaView>
CSS :
card: {
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
},
text: {
paddingRight: "2%",
textAlign: "center",
width: "100%",
fontSize: 12,
color: "black",
},
don't use flatlist. with flatlist you will always have fixed numberOfColumns but your item widths could be diff from each other. use map instead inside scrollview.
updated code :
<View style={[{ flexDirection: 'row', flexWrap: 'wrap' }]}>
{brands.map(element => {
return <View style={styles.card}>
<Text>{element.name}</Text>
</View>
})
}
</View>
styles:
card: {
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
paddingHorizontal: 5
},
Modify style of card:
card: {
flex:1,
flexDirection:"row"
height: 30,
justifyContent: "center",
backgroundColor: "#E4E4E4",
margin: 5,
borderRadius: 10,
},
or If you don't use flatlist then below code will solve your issue:
<View style={[{flexDirection: 'row', flexWrap: ' wrap'}]}>
data.map(element => {
return <Text style={{height:100}}>element.content</Text>
})
</View>
I want to achieve this animation using section list on scroll in react native.
Here is an example of food panda. This is their initial screen:
On scrolling the section list their header collapse and it becomes like this:
Here is the code of my RestaurantDetail screen:
export default function RestaurantDetail({navigation, route}) {
const headerHeight = 400;
const headerFinalHeight = 100;
const scrollY = useRef(new Animated.Value(0)).current;
const offset = headerHeight - headerFinalHeight;
const translateHeader = scrollY.interpolate({
inputRange: [0, offset],
outputRange: [0, -offset],
extrapolate: 'clamp',
});
useEffect(() => {
return navigation.addListener('focus', () => {
getRestaurantDetail();
if (user) {
getCart();
}
});
}, []);
const onScrollY = e => {
scrollY.setValue(e.nativeEvent.contentOffset.y);
headerHeight - e.nativeEvent.contentOffset.y;
console.log('Height', scrollY);
};
const onScroll = ({viewableItems}) => {
setActiveTab(viewableItems[0].section.title);
console.log('viewableItems', viewableItems[0].section.title);
};
return (
<View style={{backgroundColor: 'white', flex: 1}}>
<Animated.View
style={{
backgroundColor: 'white',
height: headerHeight,
position: 'absolute',
transform: [{translateY: translateHeader}],
}}>
<Header restaurantDetail={detail} />
<View style={{flexDirection: 'row', justifyContent: 'space-between'}}>
<MainImage restaurantDetail={detail} />
<TouchableOpacity
onPress={() => navigation.navigate('RestaurantInfo', detail)}>
<Rating />
</TouchableOpacity>
</View>
<TouchableOpacity
onPress={() => navigation.navigate('RestaurantInfo', detail)}>
<Title restaurantDetail={detail} />
</TouchableOpacity>
<HeaderTabs
activeTab={activeTab}
setActiveTab={setActiveTab}
data={itemList}
ref={ref}
/>
</Animated.View>
<View style={{paddingTop: headerHeight}}>
<SectionListeg
restaurantDetail={detail}
activeTab={activeTab}
setActiveTab={setActiveTab}
navigation={navigation}
onScroll={onScroll}
onScrollY={onScrollY}
data={itemList}
scrollEventThrottle={16}
/>
</View>
{showView && (
<View style={styles.box}>
<View style={styles.viewCartView}>
<TouchableOpacity
activeOpacity={0.7}
onPress={() => navigation.navigate('Cart', true)}>
<View style={styles.viewCartBtn}>
<View style={styles.counterView}>
<Text style={styles.text}>
{cart.cart ? cart.cart.length : cart.length}
</Text>
</View>
<Text style={styles.text}>View your cart</Text>
<Text style={styles.text}>{'Rs. ' + cart.sub_total}</Text>
</View>
</TouchableOpacity>
</View>
</View>
)}
<SafeAreaView
style={{
position: 'absolute',
top: 0,
left: 0,
right: 0,
backgroundColor: transparent ? 'transparent' : 'white',
}}>
<TopBar navigation={navigation} shouldShow={shouldShow} name={name} />
</SafeAreaView>
</View>
);
}
const styles = StyleSheet.create({
viewCartView: {
width: '100%',
height: 100,
backgroundColor: 'white',
position: 'absolute',
bottom: 0,
borderTopRightRadius: 10,
borderTopLeftRadius: 10,
alignItems: 'center',
justifyContent: 'center',
elevation: 5,
},
headerContainer: {
// position: 'absolute',
},
box: {
// ...
shadowColor: '#000',
shadowOffset: {width: 0, height: 2},
shadowOpacity: 1.0,
shadowRadius: 3,
elevation: 5,
},
viewCartBtn: {
width: '90%',
height: 50,
backgroundColor: Colors.secondary,
alignSelf: 'center',
borderRadius: 10,
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'space-evenly',
},
counterView: {
width: 30,
height: 30,
borderRadius: 50,
borderWidth: 1.5,
borderColor: 'white',
justifyContent: 'center',
alignItems: 'center',
},
text: {color: 'white', fontSize: 16, fontWeight: '700'},
});
Here is the code of my Section List:
const SectionListeg = ({
navigation,
onScroll,
data,
scrollEventThrottle,
activeTab,
onScrollY,
setIndex,
setActiveTab,
restaurantDetail,
shouldShow,
branchId,
}) => {
const headerHeight = 400;
const headerFinalHeight = 100;
const offset = headerHeight - headerFinalHeight;
const scrollY = useRef(new Animated.Value(0)).current;
const translateHeader = scrollY.interpolate({
inputRange: [0, offset],
outputRange: [0, -offset],
extrapolate: 'clamp',
});
const renderItem = ({item, index}) => {
return (
<Item
item={item}
navigation={navigation}
restaurantDetail={restaurantDetail}
/>
);
};
return (
<SectionList
sections={data}
showsVerticalScrollIndicator={false}
scrollEnabled={true}
keyExtractor={(item, index) => {
// console.log('Key Index', item.title);
if (item.id) {
return item.id;
}
}}
renderItem={renderItem}
onViewableItemsChanged={onScroll}
onScroll={onScrollY}
stickySectionHeadersEnabled={false}
renderSectionHeader={({section: {title}}) => (
<Text style={styles.header}>{title}</Text>
)}
/>
);
};
const Item = ({item, navigation, restaurantDetail}) => (
<View style={styles.item}>
<TouchableOpacity
activeOpacity={0.7}
style={{flexDirection: 'row', width: '100%'}}
onPress={() => onItemPress(item, navigation, restaurantDetail)}>
<View style={{flexDirection: 'row'}}>
<View style={{width: '70%'}}>
<Text style={styles.title}>{item.title}</Text>
<Text numberOfLines={2} style={styles.description}>
{item.description}
</Text>
<Text style={{marginTop: 5, color: Colors.black}}>
PKR {item.price}
</Text>
</View>
<View style={{width: '30%'}}>
<Image
style={styles.image}
source={{uri: 'https://uat.yallafood.pk/' + item.imageUrl}}
/>
</View>
</View>
<View
style={{
width: '100%',
height: 1,
position: 'absolute',
bottom: 0,
left: 0,
backgroundColor: Colors.grey,
}}
/>
</TouchableOpacity>
</View>
);
const styles = StyleSheet.create({
container: {
flex: 1,
marginHorizontal: 16,
},
item: {
backgroundColor: '#fff',
marginVertical: 5,
paddingStart: 20,
paddingEnd: 20,
flexDirection: 'row',
justifyContent: 'space-between',
},
header: {
fontSize: 26,
backgroundColor: '#fff',
marginLeft: 20,
fontWeight: 'bold',
color: 'black',
},
title: {
fontSize: 20,
color: 'black',
},
description: {
fontSize: 14,
color: Colors.grey,
marginTop: 5,
// width: '50%',
},
image: {
width: 80,
height: 80,
borderRadius: 10,
marginBottom: 10,
alignSelf: 'flex-end',
},
});
This is my initial Screen:
This is my screen on Scroll:
Any help will be appreciated.
On my android phone, I can only select the first choice in the autocomplete list. It works as expected on my iPhone. The list filters as I type but no matter what the first option is after filtering, I can only select the first option in the list. I tried adding a "console.log" to the touchables in the list to see if the other options are registering the touch event and they aren't. Without giving away too much of my code it is as follows:
<ScrollView contentContainerStyle={[formStyles.container]} scrollEventThrottle={64} keyboardDismissMode="on-drag" onScroll={() => { if(!this.state.hideResults){this.setState({hideResults:true})}}}>
<KeyboardAvoidingView behavior={"padding"}>
<View style={AddViewInviteeStyles.inviteeInputMainView}>
<Text style={AddViewInviteeStyles.inviteeInputInstructionText}>{this.state.contactsRetrieved ? retrievedContactText : noRetrievedContactText}</Text>
<View style={[AddViewInviteeStyles.inviteeInputAutocompleteView]}>
<AutoComplete style={[AddViewInviteeStyles.inviteeInputAutocomplete, this.state.invalidContact ? {backgroundColor : '#dd4f42'} : {}]}
data={this.state.contacts}
value={typeof this.state.invitee === "string" ? this.state.invitee : this.state.invitee.name}
containerStyle={[textStyles.container, {width: textStyles.textboxes.width}]}
placeholder={"Invite someone"}
placeholderTextColor={textStyles.datePickerTextStyle.color}
ref={(ref) => this.inviteeControl = ref}
hideResults={this.state.hideResults}
inputContainerStyle={[textStyles.container, {width: '100%', borderWidth: 0}]}
onChangeText={(text) => {
this.setState({ invitee: text });
if(this.state.invalidContact){
this.validateContact();
}
this.filterContacts(text);
}}
renderItem={({ item, i }) => (
<TouchableOpacity onPress={() => {this.setState({ invitee: item, hideResults:true, invalidContact: false })}} style={[{width: "100%"}, i > 0 ? {marginTop: 10} : {}]}>
<Text numberOfLines={1} ellipsizeMode={"tail"} style={{fontSize: responsiveFontSize(2)}}>{item.name}</Text>
</TouchableOpacity>
)}
listStyle={[{width: '100%', position: 'relative'}]}
keyExtractor={(item, i) => {return i +""}}
listContainerStyle={[textStyles.container, {width: responsiveWidth(parseInt(textStyles.textboxes.width.replace('%', ''))), position:'absolute', left: 0, top: textStyles.textboxes.height, justifyContent: 'center', alignItems: 'center', zIndex:300}]}
autoFocus={true}
blurOnSubmit={false}
underlineColorAndroid='transparent'
/>
<TouchableOpacity activeOpacity={1} style={[{width: this.state.addNewInvitee ? '10%':'20%', ...Util.filterObject(textStyles.textboxes, ["width", "minWidth"])}, !this.state.addNewInvitee? textStyles.lastTextBoxInFirstRow : {}, !this.state.addNewInvitee? textStyles.lastTextBoxInLastRow : {}, this.state.invalidContact ? {backgroundColor : '#dd4f42'} : {}]} onPress={this.addInvitee.bind(this)}>
{!this.state.invalidContact ? <Text style={[{fontSize: this.state.addNewInvitee ? responsiveFontSize(3) : responsiveFontSize(4), alignContent: 'center', justifyContent: 'center', textAlign:'center', textAlignVertical: 'center', marginTop: this.state.addNewInvitee? 11: 5}, this.state.addNewInvitee ? {marginRight: 2} : {}]}><Emoji name={"heavy_plus_sign"} /></Text> : null}
</TouchableOpacity>
{this.state.addNewInvitee ? addNewInviteeCancelBtn : null}
</View>
{this.state.invalidContact ? invalidInviteeText : null}
</View>
</KeyboardAvoidingView>
</ScrollView>
const AddViewInviteeStyles = StyleSheet.create({
inviteeInputMainView: {
alignItems: 'center',
marginTop: 40,
marginBottom: 20
},
inviteeInputInstructionText: {
...textStyles.requiredNotice,
...textStyles.notifyTextStyle,
fontSize: responsiveFontSize(2),
...Platform.select({
android:{
width: responsiveWidth(90)
}
})
},
inviteeInputAutocompleteView:{
...textStyles.container,
flexDirection: 'row',
...Platform.select({
android: {
width: responsiveWidth(parseInt(textStyles.textboxes.width.replace('%' , ''))),
},
ios:{
width: textStyles.textboxes.width
}
})
},
inviteeInputAutocomplete: {
...textStyles.textboxes,
...textStyles.firstTextBoxInFirstRow,
...textStyles.firstTextBoxInLastRow,
width: '100%'
}
});
const formStyles = StyleSheet.create({
container: {
...appStyles.container,
flexGrow: 1,
width: '100%',
}
});
const appStyles = StyleSheet.create({
container: {
backgroundColor: '#e9dec2',
}
});
const textStyles = StyleSheet.create({
container: {
alignItems: 'center',
},
textboxes: {
color: '#3c3b5f',
backgroundColor: '#F0F8FF',
width: '80%',
paddingLeft: 5,
paddingRight: 2,
minHeight: 35,
height: 50,
borderBottomColor: '#fbdd07',
borderBottomWidth: 1,
},
requiredNotice: {
color: 'grey',
fontSize: 13,
marginTop: 70,
},
firstTextBox: {
marginTop: 70,
borderTopLeftRadius: 8,
borderTopRightRadius: 8
},
firstTextBoxInFirstRow: {
borderTopLeftRadius: 8,
},
lastTextBoxInFirstRow: {
borderTopRightRadius: 8,
},
firstTextBoxWithNotice: {
borderTopLeftRadius: 8,
borderTopRightRadius: 8
},
textBoxInRow: {
borderRightWidth: 1,
borderBottomColor: '#fbdd07',
//borderRightColor: '#fbdd07'
},
notifyTextStyle: {
marginTop: '7%',
fontSize: responsiveFontSize(4),
fontWeight: "300"
}
})
It seems to be as if I need to use some extra css in order to achieve what you will see below:
I already have this component:
renderTabBar = props => (
<View style={tabViewStyles.tabBar}>
{props.navigationState.routes.map((route, i) => {
return (
<TouchableOpacity
key={route.key}
style={[
tabViewStyles.tabItem,
tabViewStyles.tabStyle,
tabViewStyles[`tabStyle_${i}`],
]}
onPress={() => this.setState({ index: i })}
>
<Text style={{ color: '#ffffff', fontFamily: 'montserratBold' }}>
{route.title}
</Text>
</TouchableOpacity>
);
})}
</View>
);
With this css on StyleSheet:
container: {
flex: 1,
},
tabBar: {
flexDirection: 'row',
paddingTop: Constants.statusBarHeight,
},
onWhite: {
color: globalStyles.whiteColor.color,
backgroundColor: globalStyles.whiteColor.backgroundColor,
},
bolderFont: {
fontFamily: 'montserratBold',
},
tabItem: {
flex: 1,
alignItems: 'center',
padding: 26,
},
tabStyle: {
marginHorizontal: 10,
marginTop: 20,
borderRadius: 2,
},
tabStyle_0: {
backgroundColor: '#ff5252',
},
tabStyle_1: {
backgroundColor: '#3da7dc',
},
});
With that above I get this:
So I am still missing the pointy part of the tab.
What else do I need to do?
You can use rotate property of Transforms as described here.
Minimal example:
<View style={{flex:1,justifyContent:'center',alignItems:'center'}}>
<View style={{width:50,height:50,backgroundColor:'green'}}></View>
<View style={{transform:[{rotateZ:'45deg'}],width:8,height:8,backgroundColor:'green',marginTop:-4}}></View>
</View>
Snack example here
If you want a pure styled solution and not an image you could do the following:
const triangle = {
width: 0,
height: 0,
backgroundColor: 'transparent',
borderStyle: 'solid',
borderLeftWidth: 50,
borderRightWidth: 50,
borderBottomWidth: 100,
borderLeftColor: 'transparent',
borderRightColor: 'transparent',
borderBottomColor: '#ff5252',
transform: [
{rotate: '180deg'}
]
}
const Triangle = React.createClass({
render: function() {
return (
<View style={[triangle, this.props.style]} />
)
}
})
Modified from https://codedaily.io/tutorials/22/The-Shapes-of-React-Native.
I have a grid view, inside each cell I have added a view and then an image , the image isn't centered the code is as follows
<ImageBackground
source={require('./images/marble.jpg')}
style={styles.backgroundImage}>
<GridView
itemDimension={130}
items={items}
style={styles.gridView}
renderItem={item => (
<View style={[styles.itemContainer, { backgroundColor: item.code }]}>
<View style={styles.CircleShapeView}>
<Image style={styles.iconItem} source={item.name}/>
</View>
</View>
)}
/>
</ImageBackground>
and styles are
const styles = StyleSheet.create({
backgroundImage: {
flex: 1,
resizeMode: 'cover', // or 'stretch'
},
CircleShapeView: {
width: 100,
height: 100,
borderRadius: 100,
backgroundColor: '#00BCD4'
},
gridView: {
paddingTop: 50,
flex: 1,
},
itemContainer: {
justifyContent: 'center',
alignItems:'center',
height:130
},
iconItem: {
alignItems:'center',
justifyContent: 'center'
}
});
the output looks like this
Image should be at the centre of the circle, but its not.
Your image is inside a view 'CircleShapeView'
CircleShapeView: {
width: 100,
height: 100,
borderRadius: 100,
backgroundColor: '#00BCD4',
justifyContent: 'center',
alignItems: 'center'
}
set in view
justifycontent:center
alignitems:center