Flexbox alignment issue in react-native - react-native

I'm trying to align the contents of a View component into left and right side of the screen. Unfortunately, whatever I do, I can only align the parent View and not the child View components.
In the snippet below, item is the Parent View, leftIcon and title are supposed to be aligned together in the left and rightArrow is supposed to be aligned in the right.
<TouchableOpacity onPress={() => navigation.navigate(`${item.page}`)}>
<View style={styles.item}>
<Text style={styles.leftIcon}>a</Text>
<Text style={styles.title}>{item.title}</Text>
<Text style={styles.rightArrow}> > </Text>
</View>
</TouchableOpacity>
const styles = StyleSheet.create({
item: {
//backgroundColor: '#f9c2ff',
paddingTop: 7,
marginVertical: 4,
marginHorizontal: 16,
flex: 1,
flexDirection: 'row',
},
leftIcon: {
fontSize: 25,
paddingRight: '5%',
alignSelf: 'flex-start',
},
title: {
fontSize: 25,
alignSelf: 'flex-start',
},
rightArrow: {
fontSize: 25,
alignSelf: 'flex-end'
}
});
This might be an incorrect approach, but what can be done to achieve this?

You can wrap leftIcon and title in a view with a flexDirection: 'row' style.
Then add justifyContent: 'space-between' to your item styles.
Example (using inline styles):
<TouchableOpacity>
<View
style={{
marginVertical: 4,
marginHorizontal: 16,
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
}}>
<View style={{ flexDirection: 'row' }}>
<Text
style={{
fontSize: 25,
paddingRight: '5%',
}}>
a
</Text>
<Text style={{ fontSize: 25 }}>Title</Text>
</View>
<Text style={{ fontSize: 25 }}> > </Text>
</View>
</TouchableOpacity>

Related

Change font color with TouchableHighlight

How to change the font color of the button, the problem is that the font color doesn't look good so each time the user tap on the button I need to change the font color too.
My approach:
Normal Button
Pressed Button
<TouchableHighlight
underlayColor="#E5E6EA"
onPress={onOpen2}
style={{
fontFamily: "AktivGroteskCorp",
paddingLeft: 15,
paddingRight: 15,
borderRadius: 25.5,
flexDirection: "row",
justifyContent: "center",
marginBottom: 15,
width: vw * 67.2,
height: vw * 13.6,
alignItems: "center",
alignSelf: "center",
borderColor: "#E5E6EA",
borderWidth: 1,
}}
>
<Text
style={{
color: "#ffffff",
fontWeight: "bold",
fontSize: 16,
textAlign: "center",
alignSelf: "center",
}}
>
LOG IN
</Text>
</TouchableHighlight>
Here is a functional way
First, create useState then manipulate it on onPressIn/onPressOut
const TouchableHighlightExample = () => {
const [BtnColor, setBtnColor] = useState("red");
return (
<View>
<TouchableHighlight onPressIn={()=>setBtnColor("blue")} onPressOut={()=>setBtnColor("red")}>
<View>
<Text style={{color: BtnColor}}>Touch Here</Text>
</View>
</TouchableHighlight>
</View>
);
}
using onPressIn and onPressOut
https://reactnative.dev/docs/pressable#onpressin
state = {
fontColor: 'red',
}
<TouchableHighlight
onPressIn={()=>{ this.setState({fontColor:'blue'});}}
onPressOut={()=>{ this.setState({fontColor:'red'});}}
>
<Text
style={{
color: this.state.fontColor,
}}
>
LOG IN
</Text>
</TouchableHighlight>

How to keep props in a child component inside a Flatlist?

I'm currently using React-Native Flatlist with a custom component to show data.
The custom component show a card an should show a modal (RBSheet to be exact) on click.
The problem is that props doesn't look to be keept, when I press on a card, I get the props data from another card.
I thought about to get the clicked element on the parent, but I was not able to do through the flatlist to show the modal with the correct data.
I was not able to bind the card to get the data from its props.
My Custom Component (Entry.js)
return (
<View
style={{
flexDirection: "row",
alignContent: "center",
alignItems: "center",
textAlign: "center",
marginBottom: "5%"
}}
>
<View style={{ flexDirection: "row" }}>
<View
style={{
flex: 1,
flexDirection: "row",
justifyContent: "center",
alignContent: "center",
alignItems: "center",
textAlign: "justify"
}}
>
<Card
style={{
padding: 10,
elevation: 2,
margin: 10,
textAlign: "center",
width: "95%",
borderRadius: 20
}}
onPress={() => this.RBSheet.open()}
>
<Card.Content>
<Image
source={{
uri:
"http://guiadigital.madridactiva.anovagroup.es/" +
props.item.fotos[0]
}}
style={{
width: "100%",
height: 200,
padding: 5,
borderRadius: 10
}}
PlaceholderContent={<ActivityIndicator />}
/>
<Text
style={{
color: "#484855",
fontSize: RF(3.5),
paddingTop: 25,
textAlign: "center"
}}
>
{props.item.nombre}
</Text>
<Text
style={{
color: "#484855",
fontSize: RF(2),
paddingTop: 15,
textAlign: "center"
}}
>
{props.item.descripcion.split(".")[0]}
</Text>
</Card.Content>
</Card>
</View>
</View>
<RBSheet
ref={ref => {
this.RBSheet = ref;
}}
animationType="slide"
closeOnPressMask={true}
height={RF(80)}
duration={100}
customStyles={{
container: {
justifyContent: "center",
alignItems: "center",
textAlign: "center",
alignContent: "center",
borderTopLeftRadius: 20,
borderTopRightRadius: 20
}
}}
>
<Text
style={{
color: "#484855",
fontSize: RF(3.5),
paddingTop: 25,
textAlign: "center"
}}
>
{props.item.nombre}
</Text>
</RBSheet>
</View>
);
My Flatlist (Just in case)
<View
style={{
flex: 1,
justifyContent: "center",
textAlign: "center",
alignItems: "center",
marginTop: "5%"
}}
>
<FlatList
style={{
width: "100%",
alignContent: "center",
backgroundColor: "#000"
}}
data={this.state.data}
showsVerticalScrollIndicator={true}
keyExtractor={item => item.nombre}
renderItem={({ item }) => <Entry item={item} />}
/>
</View>
I would like to be able to handle the data either in my custom component or in the flatlist screen
With shouldComponentUpdate i think you should be able to control the datas inside the child component. See the react docs for more info https://it.reactjs.org/docs/react-component.html#shouldcomponentupdate
I already fix my issue, the problem was that the component wasn't declare as class so it doesn't keep props properly.
Once the component is declared and exported as class, every item in the flatlist is an object with its own props.

How to align multiline text in react native

In my screen, I need to split the text into column view and need to align the right side text with the left side text. also, need to show the whole text line by line. Tested with giving some height, width, position: absolute but didn't work. Any idea how to solve this?
I'll post my current code and screenshot for your ref.
Many thanks for your help
<View style={styles.twoCol}>
<View style={styles.leftField}>
<Text style={styles.leftFieldTitle}>Location:</Text>
</View>
<View style={styles.locationRightSide}>
<Text style={styles.rightFieldTitle}>{location}</Text>
</View>
</View>
const styles = StyleSheet.create({
twoCol: {
alignItems: 'center',
flexDirection: 'row',
marginTop: 25,
},
leftField: {
alignItems: 'flex-end',
width: '25%',
},
leftFieldTitle: {
fontWeight: '700',
color: 'black'
},
},
locationRightSide: {
width: '70%',
alignItems: 'flex-start',
paddingLeft: 10
},
rightFieldTitle: {
fontSize: RF(2.8),
color: 'black'
},
)}
Problem solved!!! Thanks everyone!
<View style={{
padding: 10,
flexDirection: "row",
marginLeft: 10,
marginRight: 5,
marginTop: 5,
marginBottom: 3,
justifyContent: "flex-start",
width: '95%',
}} >
<View style={{
position: 'absolute',
marginTop: 10
}}>
<Text style={styles.leftFieldTitle}>Location:</Text>
</View>
<View style={{ marginLeft: '26%' }}>
<Text style={styles.rightFieldTitle}>{location}</Text>
</View>
</View>

RN Android: button takes too much space when text on 2 lines

I have this button
const TestButton = ({ text }) => (
<View
style={{
width: '100%',
marginTop: 10,
padding: 10,
backgroundColor: 'red',
flexDirection: 'row',
justifyContent: 'center',
}}>
<View
style={{
backgroundColor: 'green',
padding: 10,
flexDirection: 'row',
alignItems: 'center',
}}>
<Text numberOfLines={2}>{text}</Text>
</View>
</View>
);
I want the button to be the smallest possible, and centered.
Android
On Android, as you can see it's not really the case. For the 3 case we can clearly see that the button (green) is much larger than it should be and takes all available space.
iOS
On iOS as you can see it seems to work as I expect.
Is this a bug? Are there any workaround to solve this problem on Android?
Here is an Expo snack to reproduce.
Try this
const TestButton = ({ text }) => (
<View
style={{
width: '100%',
marginTop: 10,
padding: 10,
backgroundColor: 'red',
flexDirection: 'row',
justifyContent: 'center',
}}>
<View
style={{
padding: 10,
flexDirection: 'row',
alignItems: 'center',
}}>
<Text numberOfLines={2}
style = {{
backgroundColor: 'green',
padding:10
}}>
{text}
</Text>
</View>
</View>
);
I could solve my issue with wrapping my labels into container:
itemContainer: {
flex: 1,
marginHorizontal: 25,
paddingVertical: 15,
flexDirection: "row",
justifyContent: "space-between",
alignItems: "center"
},
itemView: {
width: "100%"
},
newsTitle: {
fontSize: 20,
color: darkBlue,
paddingRight: 20,
fontFamily: "Helvetica-middle",
borderColor: darkBlue,
borderWidth: 1
},
newsChannel: {
paddingTop: 10,
fontSize: 16,
fontFamily: "Helvetica",
color: darkGrey
},
return (
<TouchableOpacity style={styles.itemContainer}>
<View style={styles.itemView}>
<Text style={styles.newsTitle}>{news.title}</Text>
<Text style={styles.newsChannel}>{newsChannelTitle}</Text>
</View>
<ArrowIcon />
</TouchableOpacity>
);

React Native: How to align inline text?

I want to do this, where both of the texts are on 1 horizontal line and one of them is in the center and the other is on the right:
This is what I have, ignore the colors (it doesn't work at all):
styles:
rowLabelText: {
color: "#0B1219",
fontFamily: Fonts.Knockout31JuniorMiddleWeight,
fontSize: 16.0,
},
Markup:
<View style={{flexDirection: 'row', height: 30, flexWrap: 'wrap', backgroundColor: 'green'}}>
<View style={{ flex: 1, backgroundColor: 'red', justifyContent: 'center', alignSelf: 'center'}}>
<Text style={styles.rowLabelText}>
adjkfdasjkfaskj
</Text>
</View>
<View style={{ flex: 1, backgroundColor: 'blue', justifyContent: 'center', alignSelf: 'flex-end' }}>
<Text style={styles.rowLabelText}>
adjkfdasjkfaskj
</Text>
</View>
</View>
I am having trouble. Could someone assist me?
It looks like your problem is with with alignSelf you want to use alignItems.
This is how your code will look like.
Your View:
<View style={styles.textContainer}>
<View style={styles.leftContainer}>
<Text style={styles.rowLabelText}>
adjkfdasjkfaskj
</Text>
</View>
<View style={styles.rightContainer}>
<Text style={styles.rowLabelText}>
adjkfdasjkfaskj
</Text>
</View>
</View>
Your styles:
textContainer:{
flexDirection: 'row',
height: 30,
backgroundColor: 'green'
},
leftContainer:{
flex: 1,
justifyContent: 'center',
alignItems:'center',
backgroundColor: 'red',
},
rightContainer:{
flex: 1,
justifyContent: 'center',
alignItems: 'flex-end',
backgroundColor: 'blue',
},
rowLabelText: {
color: "#0B1219",
fontSize: 16.0,
},
One way to center text with respect to the entire width of the screen while also having some text to the right side of the centered text is to use absolute positioning on the right text.
By using absolute positioning on the right text, it will not affect the position of the centered text.
<View style={{flexDirection: 'row'}}>
<View style={{flex:1, alignItems: 'center', backgroundColor: 'red'}}>
<Text>50%</Text>
</View>
<View style={{position:'absolute', right: 20, backgroundColor: 'blue'}}>
<Text>+$0.80</Text>
</View>
</View>