I want to have a button where the middle text is centered in the middle and an additional text is pushed to the right, like in this image:
https://i.imgur.com/oNDeFJo.png
I tried marginLeft property but react-native flexbox model behaves differently than css, this is my code:
<TouchableHighlight style={{ flex:1, height:40, backgroundColor:'rgb(255,216,0)', borderRadius:5 }}>
<View style={{ flex:1, height:40, flexDirection:'row', alignItems:'center', justifyContent:'center', paddingHorizontal:20 }}>
<Text style={{ fontSize:16, color:'black' }}>Add to cart</Text>
<Text style={{ fontSize:16, color:'black', marginLeft:'auto' }}>19:00</Text>
</View>
</TouchableHighlight>
You can use the following code:
<TouchableHighlight style={{ height:40, backgroundColor:'rgb(255,216,0)', borderRadius:5 }}>
<View style={{ height:40, flexDirection:'row', paddingHorizontal:20; width: 100%;}}>
<Text style={{ fontSize:16, color:'black', flex:2; text-align: center; }}>Add to cart</Text>
<Text style={{ fontSize:16, color:'black', flex:1; text-align: right}}>19:00</Text>
</View>
</TouchableHighlight>
This ratio is 2:1, you can even change it to 3:1 according to the need.
For this, just change flex:3 from first <Text/>.
Adjust flex value according to your requirement.
For the web version, you can verify this using the following code snippet:
<div class="box" style="display: flex; width: 100%;">
<div style="flex:2; text-align: center;">One</div>
<div style="flex:1; text-align: right">Two</div>
</div>
You can add absolute position so both texts are individual.
in addition it will always let the main text align to the center.
<TouchableHighlight style={{ flex:1, height:40, backgroundColor:'rgb(255,216,0)', borderRadius:5 }}>
<View style={{ flex:1, height:40, flexDirection:'row', alignItems:'center', justifyContent:'center', paddingHorizontal:20 }}>
<Text style={{ fontSize:16, color:'black' }}>Add to cart</Text>
</View>
<View style={{position: 'absolute', right: 3, height: 40, alignItems: 'center', justifyContent: 'center'}}>
<Text style={{ fontSize:16, color:'black', marginLeft:'auto' }}>19:00</Text>
</View>
</TouchableHighlight>
Related
I'm trying to arrange my cards into something like this
But heres what I got
As you can see the TouchableOpacity (yellow color) takes more than half of the container width (orange color).
I've tried may things by adding width: "50%" and set alignItems with flex-start, flex-end, etc but it only make things worse.
Here's my card component code
const SmallMateriCard = (props) => {
return (
<NativeBaseProvider >
<Box maxW={"70%"} alignItems="flex-start" style={{backgroundColor:"blue"}}>
{/* <Pressable onPress={props.onPress}> */}
<Box
borderRadius={18}
overflow="hidden"
style={{
width: "100%",
backgroundColor: 'white',
shadowColor: '#000',
shadowOffset: {
width: 0,
height: 0,
},
shadowOpacity: 0.1,
shadowRadius: 3,
elevation: 4,
}}>
<Box>
<AspectRatio w="100%" ratio={6/5} >
{props.cardIcon && (
<Image
borderRadius={18}
source={{uri: props.cardIcon}}
alt="image"
/>
)}
</AspectRatio>
</Box>
<Stack px="6" py="6" >
<Text
style={[
font.family.extrabold,
{ fontSize: 15, color: color.primary },
]}>
{props.title}
</Text>
</Stack>
</Box>
{/* </Pressable> */}
</Box>
</NativeBaseProvider>
);
};
export default SmallMateriCard;
and here's my screen code
const UKKSekunderScreen = ({ navigation }) => {
return (
<SafeAreaView>
<View
style={[mixins.margin(16,16)]}>
<ScrollView >
<View style={[mixins.margin(16,16), layout.display.flex, layout.justify.between, { backgroundColor:"orange", flexDirection: 'row', flexWrap: 'wrap' }]}>
{UKK_SEKUNDER.map((item, key) => (
<TouchableOpacity key={key} style={{ backgroundColor:"yellow", }}>
<View
style={[layout.margin.vertical(10)]}
>
<SmallMateriCard {...item} />
</View>
</TouchableOpacity>
))}
</View>
</ScrollView>
</View>
</SafeAreaView>
);
};
export default UKKSekunderScreen;
Thanks in advance.
EDIT
Gaurav's solution works but there's a new problem when I integrated it with my expandable component. The cards are overlaps when the component is collapsed.
EDIT 2
Solved by adding overflow: 'hidden'.
Hey check this please https://snack.expo.dev/HUhqzIpYv
Hope it helps :)
I believe your desired output would be a flex row with wrap enabled such as:
<View style={{flex: 1, justifyContent: 'flex-start', alignItems: 'center'}}>
<View style={{
justifyContent: 'flex-start',
alignItems: 'center',
flexDirection:'row',
flexWrap: 'wrap'
}}>
<Box style={{width: '50%'}} {...} />
<Box style={{width: '50%'}} {...} />
<Box style={{width: '50%'}} {...} />
<Box style={{width: '50%'}} {...} />
....
</View>
</View>
You could add some padding and margin to the box to add some space in-between them.
Edit: Here's an example with plain text, just to notice the layout:
<View style={{flex: 1, alignItems: 'center', justifyContent: 'center'}}>
<View
style={{
justifyContent: 'flex-start',
alignItems: 'center',
flexDirection: 'row',
flexWrap: 'wrap',
}}>
<Text
style={{width: '40%', borderWidth: 2, padding: '10%', margin: '5%', textAlign: 'center'}}>
Text
</Text>
<Text
style={{width: '40%', borderWidth: 2, padding: '10%', margin: '5%', textAlign: 'center'}}>
Text
</Text>
<Text
style={{width: '40%', borderWidth: 2, padding: '10%', margin: '5%', textAlign: 'center'}}>
Text
</Text>
<Text
style={{width: '40%', borderWidth: 2, padding: '10%', margin: '5%', textAlign: 'center'}}>
Text
</Text>
<Text
style={{width: '40%', borderWidth: 2, padding: '10%', margin: '5%', textAlign: 'center'}}>
Text
</Text>
<Text
style={{width: '40%', borderWidth: 2, padding: '10%', margin: '5%', textAlign: 'center'}}>
Text
</Text>
<Text
style={{width: '40%', borderWidth: 2, padding: '10%', margin: '5%', textAlign: 'center'}}>
Text
</Text>
</View>
</View>
EDIT: I've implemented what I needed using jsPDF instead of react-pdf/renderer so guess below doesn't matter anymore! Will leave up in case an answer helps someone in future.
I've tried troubleshooting everything I can think of with this one and need some help!
I'm trying to render a dynamic PDF using react-pdf/renderer but I keep getting the error message "Cannot read properties of undefined (reading: 'height') in console and the PDF does not display on web page.
So initially I had used <p> elements and from searching this is a no go so I switched all of those out for the <Text> but error persists. I was also attempting to style with tailwind before but I've also been through and removed all of that to use the styling from the docs.
I'm now at a loss, can't see anything else I shouldn't be doing. I've tried commenting out the mapping and moment functions as well just in case and that made no difference.
Code is below, first snippet is where I'm trying to render and then the second snippet is the full component. It wasn't originally in the "dashboard" which is why the invoice is an empty array, just moved it here as part of my troubleshooting (also didn't help).
Any guidance will be appreciated!
import React from "react";
import { useSelector } from "react-redux";
import { EuiFlexGroup, EuiFlexItem } from "#elastic/eui";
import InvoicePage from "../../pdf/InvoicePage";
import { PDFViewer } from "#react-pdf/renderer";
function DashboardScreen() {
const auth = useSelector((state) => state.auth);
const user = auth.user;
const viewInvoice = [""];
return (
<div className='flex flex-col mx-auto'>
<EuiFlexGroup
direction='column'
justifyContent='center'
alignItems='center'
className='w-full'
>
<EuiFlexItem>
<h2 className='text-5xl mt-10'>{user.firstName}'s Dashboard</h2>
</EuiFlexItem>
<EuiFlexItem className='mt-20 text-lg'>
Dashboard Coming Soon!
</EuiFlexItem>
</EuiFlexGroup>
<PDFViewer>
<InvoicePage user={user} invoice={viewInvoice} />
</PDFViewer>
</div>
);
}
export default DashboardScreen;
import { Page, Document, View, Text, StyleSheet } from "#react-pdf/renderer";
import React from "react";
import moment from "moment";
function InvoicePage({ invoice, user }) {
const styles = StyleSheet.create({
page: {
backgroundColor: "white",
},
});
return (
<Document>
<Page size='A4' style={styles.page}>
<View style={{ display: "flex" }}>
<View
style={{
display: "flex",
flexDirection: "column",
width: "50%",
border: "solid 1px gray",
padding: 8,
}}
>
<Text>Invoice To:</Text>
<Text>{invoice.clientName}</Text>
<Text>{invoice.clientAddrOne}</Text>
<Text>{invoice.clientCity}</Text>
<Text>{invoice.clientPostcode}</Text>
</View>
<View
style={{
display: "flex",
flexDirection: "column",
width: "50%",
marginLeft: 80,
border: "solid 1px gray",
padding: 8,
}}
>
<Text>Invoice From:</Text>
<Text>
{user.firstName} {user.secondName}
</Text>
<Text>{user.addrOne || ""}</Text>
<Text>{user.city || ""}</Text>
<Text>{user.postcode || ""}</Text>
</View>
</View>
<View
style={{
display: "flex",
flexDirection: "column",
marginTop: 32,
border: "1px solid gray",
padding: 8,
}}
>
<View style={{ display: "flex", width: "100%" }}>
<Text style={{ width: "35%", textDecoration: "underline" }}>
Invoice Number
</Text>
<Text style={{ width: "35%", textDecoration: "underline" }}>
Date Sent
</Text>
<Text style={{ width: "35%", textDecoration: "underline" }}>
Date Due
</Text>
</View>
<View style={{ display: "flex", width: "100%", marginTop: 8 }}>
<Text style={{ width: "35%", paddingLeft: 48 }}>
{invoice.invoiceNumber}
</Text>
<Text style={{ width: "35%" }}>
{moment(invoice.sentDate).format("Do MMMM YYYY")}
</Text>
<Text style={{ width: "35%" }}>
{moment(invoice.dueDate).format("Do MMMM YYYY")}
</Text>
</View>
</View>
<View
style={{
display: "flex",
flexDirection: "column",
border: "1px solid gray",
marginTop: 8,
marginBottom: 8,
padding: 8,
}}
>
<View style={{ display: "flex", width: "100%", marginBottom: 8 }}>
<Text style={{ width: "50%", textDecoration: "underline" }}>
Task Description
</Text>
<Text style={{ width: "17%", textDecoration: "underline" }}>
Hours
</Text>
<Text style={{ width: "17%", textDecoration: "underline" }}>
Rate
</Text>
<Text style={{ width: "17%", textDecoration: "underline" }}>
Price
</Text>
</View>
{invoice.tasks.map((task) => {
const time = task.hours + task.minutes / 60;
const price = time * invoice.hourlyRate;
return (
<View style={{ display: "flex", width: "100%" }}>
<Text style={{ width: "50%" }}>{task.taskDescription}</Text>
<Text style={{ width: "17%" }}>{time.toFixed(2)}</Text>
<Text style={{ width: "17%" }}>{invoice.hourlyRate}</Text>
<Text style={{ width: "17%" }}>£{price.toFixed(2)}</Text>
</View>
);
})}
</View>
<View style={{ display: "flex", justifyContent: "space-between" }}>
<View
style={{
display: "flex",
flexDirection: "column",
border: "1px solid gray",
padding: 8,
width: "40%",
}}
>
<View style={{ display: "flex" }}>
<View style={{ textDecoration: "underline", marginBottom: 8 }}>
<Text>Payment Details</Text>
</View>
</View>
<View>
<View>
<Text>Payment Method:</Text>
</View>
<View>
<Text>{invoice.paymentMethod}</Text>
</View>
</View>
<View
style={{ display: "flex", flexDirection: "column", marginTop: 8 }}
>
<View>
<Text>Account Number:</Text>
</View>
<View>
<Text>{invoice.accountNumber}</Text>
</View>
</View>
<View
style={{ display: "flex", flexDirection: "column", marginTop: 8 }}
>
<View>
<Text>Sort Code:</Text>
</View>
<View>
<Text>{invoice.sortCode}</Text>
</View>
</View>
</View>
<View
style={{ display: "flex", flexDirection: "column", width: "50%" }}
>
<View
style={{ display: "flex", border: "1px solid gray", padding: 8 }}
>
<View style={{ width: "50%" }}>
<Text>Total:</Text>
</View>
<View style={{ width: "50%" }}>
<Text>£0.00</Text>
</View>
</View>
<View
style={{ display: "flex", flexDirection: "column", marginTop: 8 }}
>
Thank you for your business!
</View>
</View>
</View>
</Page>
</Document>
);
}
export default InvoicePage;
Just a simple solution, I think work in your case. You have to mention height of your <PDFViewer> element like
<PDFViewer style={{ height: "50vh", width: "100%"}}>
<InvoicePage user={user} invoice={viewInvoice} />
</PDFViewer>
OR
<PDFViewer style={styles.PDFContainer}>
<InvoicePage user={user} invoice={viewInvoice} />
</PDFViewer>
const styles = StyleSheet.create({
PDFContainer: {
width: "100%",
height: "50vh", //As per your page layout
}
}
I know this question is old, but anyway...
It's looks like you need to add <Text> tag to Thank you for your business! at the end of file.
See the following snack
I need to adapt the height of the ScrollView to its children. It seems that ScrollView is using { flex: 1 } by default (not sure). Any ideas how to make it possible?
<View style={{ flex: 1 }}>
<ScrollView horizontal style={{ backgroundColor: 'red' }}>
<View
style={{ width: 60, height: 30, marginLeft: 5, backgroundColor: 'lime' }}
/>
</ScrollView>
<View style={{ flex: 1, backgroundColor: 'yellow' }} />
</View>
Thank you.
Note: Is it possible to do it without using { height: 30 } ?
Wrapping the ScrollView inside a View does the trick.
<View style={{ flex: 1 }}>
<View>
<ScrollView horizontal style={{ backgroundColor:"red" }}>
<View style={{ width: 60, height: 30, marginLeft: 5, backgroundColor: "lime" }} />
</ScrollView>
</View>
<View style={{ flex: 1, backgroundColor:"yellow" }} />
</View>
I have a screen called Tools, which allows me to redirect my user to multiple child screens.
I want to align the text in the middle of the image. I got to do this:
But I have the impression that it is not perfectly aligned in the center, an offset is created, I do not know if you can see it.
Could you give me your help on this point, how can I improve this?
The code :
export default function Tools({navigation}) {
return (
<ScrollView>
<View style={styles.screen}>
<View style={styles.row}>
<Text style={{marginHorizontal: 25, fontSize: 16}}>{i18n.t("tools.action.account")}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('Account')}
style={styles.roundButton}>
<Image source={require("../../assets/images/accounting.png")} style={styles.img}/>
</TouchableOpacity>
</View>
<View style={styles.row}>
<TouchableOpacity
onPress={() => navigation.navigate('Scan')}
style={styles.roundButton}>
<Image source={require("../../assets/images/barcode.png")} style={styles.img}/>
</TouchableOpacity>
<Text style={{marginHorizontal: 25, fontSize: 16}}>{i18n.t("tools.action.scanProducts")}</Text>
</View>
<View style={styles.row}>
<Text style={{marginHorizontal: 25, fontSize: 16}}>{i18n.t("tools.action.ticket")}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('Tickets')}
style={styles.roundButton}>
<Image source={require("../../assets/images/ticket.png")} style={styles.img}/>
</TouchableOpacity>
</View>
<View style={styles.row}>
<TouchableOpacity
onPress={() => navigation.navigate('Checkout')}
style={styles.roundButton}>
<Image source={require("../../assets/images/cash-register.png")}
style={styles.img}/>
</TouchableOpacity>
<Text style={{marginHorizontal: 25, fontSize: 16}}>{i18n.t("tools.action.cash")}</Text>
</View>
<View style={styles.row}>
<Text style={{marginHorizontal: 25, fontSize: 16}}>{i18n.t("tools.action.products")}</Text>
<TouchableOpacity
onPress={() => navigation.navigate('Products')}
style={styles.roundButton}>
<Image source={require("../../assets/images/products.png")} style={styles.img}/>
</TouchableOpacity>
</View>
</View>
</ScrollView>
);
}
The style :
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent:'center',
width : '100%',
},
roundButton: {
marginTop: 20,
width: 100,
height: 100,
justifyContent: 'center',
alignItems: 'center',
padding: 10,
borderRadius: 100,
backgroundColor: 'orange',
},
img: {
width: 50,
height: 50,
},
Remove marginTop from roundButton:
roundButton: {
width: 100,
height: 100,
justifyContent: 'center',
alignItems: 'center',
padding: 10,
borderRadius: 100,
backgroundColor: 'orange',
},
Working Example: Expo Snack
I added pink background just to highlight the row and show that text is centered, remove it later :)
Full Source Code:
export default function Tools({ navigation }) {
return (
<ScrollView>
<View style={styles.screen}>
<View style={styles.row}>
<Text style={{ marginHorizontal: 25, fontSize: 16 }}>
{('tools.action.account')}
</Text>
<TouchableOpacity
onPress={() => navigation.navigate('Account')}
style={styles.roundButton}>
<Image
source={{uri: "https://i.stack.imgur.com/t8vJf.jpg?s=328&g=1"}}
style={styles.img}
/>
</TouchableOpacity>
</View>
<View style={styles.row}>
<TouchableOpacity
onPress={() => navigation.navigate('Scan')}
style={styles.roundButton}>
<Image
source={{uri: "https://i.stack.imgur.com/t8vJf.jpg?s=328&g=1"}}
style={styles.img}
/>
</TouchableOpacity>
<Text style={{ marginHorizontal: 25, fontSize: 16 }}>
{('tools.action.scanProducts')}
</Text>
</View>
<View style={styles.row}>
<Text style={{ marginHorizontal: 25, fontSize: 16 }}>
{('tools.action.ticket')}
</Text>
<TouchableOpacity
style={styles.roundButton}>
<Image
source={{uri: "https://i.stack.imgur.com/t8vJf.jpg?s=328&g=1"}}
style={styles.img}
/>
</TouchableOpacity>
</View>
<View style={styles.row}>
<TouchableOpacity
style={styles.roundButton}>
<Image
source={{uri: "https://i.stack.imgur.com/t8vJf.jpg?s=328&g=1"}}
style={styles.img}
/>
</TouchableOpacity>
<Text style={{ marginHorizontal: 25, fontSize: 16 }}>
{('tools.action.cash')}
</Text>
</View>
<View style={styles.row}>
<Text style={{ marginHorizontal: 25, fontSize: 16 }}>
{('tools.action.products')}
</Text>
<TouchableOpacity
style={styles.roundButton}>
<Image
source={{uri: "https://i.stack.imgur.com/t8vJf.jpg?s=328&g=1"}}
style={styles.img}
/>
</TouchableOpacity>
</View>
</View>
</ScrollView>
);
}
const styles = StyleSheet.create({
screen: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
row: {
flexDirection: 'row',
alignItems: 'center',
justifyContent: 'center',
width: '100%',
backgroundColor: "pink",
margin: 5
},
roundButton: {
width: 100,
height: 100,
justifyContent: 'center',
alignItems: 'center',
padding: 10,
borderRadius: 100,
backgroundColor: 'orange',
},
img: {
width: 50,
height: 50,
},
});
I have a MapView, with a text above it:
<View style={{ height: 310, alignItems: 'center', marginBottom: 10 }}>
<MapView style={ { height: 300, width: 350, } } initialRegion= .. >
<View style={{ height: 60, backgroundColor: 'rgba(255,255,255,0.7)' , flexDirection: 'column'}}>
<View style={{flexDirection: 'row'}} >
<Text style={{ fontSize: 20, color: 'black' }}> {this.state.title} </Text>
</View>
<View style={{flexDirection: 'row'}}>
<Text style={{ marginTop: 5, fontSize: 15, color: 'black', marginRight: 13}}> {this.state.startLoc.name} </Text>
<Text style={{ marginTop: 5, fontSize: 15, backgroundColor: 'transparent', color: 'black' }}> {buildTimeString(new Date(this.state.startDate))} </Text>
<Text style={{ marginTop: 5, fontSize: 15, backgroundColor: 'transparent', color: 'black' }}> {getDistanceOneToOne(this.state.startLoc, this.state.destinationLoc).distance} </Text>
</View>
</View>
..
</View>
Sometimes it displays the two texts (lines) right, but most of the times it displays them wrong (bot above each other):
What could be the issue?