React Native layout - text/icons appear "under" the image instead of below - css

I have the following layout:
<SafeAreaView style={styles.container}>
<Swipe
onSwipeRight={this.handleLikedJob}
onSwipeLeft={this.handlePassedJob}
keyProp="id"
data={jobs}
renderCard={this.renderCards}
renderNoMoreCards={this.renderNoMoreCards}
onCardClick={this.showCardInfo}
/>
<View styles={styles.buttonArea}>
<ActionButton
buttonColor="rgba(231,76,60,1)"
/>
<ActionButton
buttonColor="rgba(231,76,60,1)"
/>
<ActionButton
buttonColor="rgba(231,76,60,1)"
/>
</View>
</SafeAreaView>
Unfortunately I'm not seeing any action buttons.
my styles:
container: {
flex: 1,
backgroundColor: '#fff',
},
imageView: {
flex: 1,
alignSelf: 'stretch',
width: win.width * 0.97,
height: win.height * 0.55,
margin: 5,
elevation: 5,
shadowColor: '#202020',
shadowOffset: { width: 0, height: 0 },
shadowRadius: 5,
},
buttonArea: {
flex: 1,
},
Swipe component view is from the prop sent to it (renderCards):
<View style={styles.imageView}>
<ImageBackground
source={{ uri: image }}
style={{ width: '100%', height: '100%' }}
imageStyle={{ borderRadius: 15 }}
>
<Text style={styles.itemTitle}>
{job.title}
</Text>
<View style={styles.locationContainer}>
<Icon type="material" name="location-on" color="white" />
<Text style={styles.locationText}>
{job.location}
away
</Text>
</View>
</ImageBackground>
</View>
As far as I read, the buttonArea should appear below the Swipe component, not under it (which is not visible).
Any idea what I'm missing here?
My goal is just to show the buttonArea right below the Swipe component.
Swipe component has position absolute.

Related

Flexbox does not constraint itself to parent width and always overflows

I am struggling to understand why flexbox will not constraint itself to the parent component width. I have tried multiple approaches without much luck and my buttons are always overflowing the parent component.
Here is what I have so far: https://snack.expo.io/#mohammedri/smart-bagel
and here is what I want instead (top 4 red boxes are buttons, next red box is a text field and the last one is the reset table button):
I am using UI kitten for theming, but don't think it should impact the outcome. I have tried resizeMode as well, but it doesn't seem to work. Any help is appreciated.
I have posted majority of my code below:
App.js:
export default function App() {
const Tab = createBottomTabNavigator();
return (
<ApplicationProvider {...eva} theme={eva.light}>
<SafeAreaView style={styles.container}>
<NavigationContainer>
{/* ... More code */}
<Tab.Screen name="Home" component={HomeScreen} />
{/* ... More code */}
</Tab.Navigator>
</NavigationContainer>
</SafeAreaView>
</ApplicationProvider>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: "#fff",
},
});
HomeScreen.js:
return (
<WaterIntakeContext.Provider value={{dayTotalWater, setDayTotalWater}}>
<View style={styles.container}>
<View style={styles.statusContainer}>
<Text style={styles.titleText} category="h3">some text</Text>
<Text style={styles.subtitleText} category="h6">some text</Text>
<Text style={styles.statusTextWater} category="p1">some text</Text>
<Text style={styles.statusTextWR} category="p1">You have gone to the washroom {numTimesDay} times today with each trip being an average of {avgTime} seconds long.</Text>
<Divider></Divider>
</View>
<View style={styles.timerContainer}>
<Timer setTimerStateChanged={setTimerStateChanged} />
</View>
<View style={styles.waterContainer}>
<Divider></Divider>
<WaterIntake />
</View>
</View>
</WaterIntakeContext.Provider>
);
};
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "column",
justifyContent: "flex-start",
flexWrap: 'wrap',
backgroundColor: "#fff",
paddingRight: 30,
paddingLeft: 30,
paddingTop: 20
},
statusContainer: {
borderLeftWidth: 1,
borderRightWidth: 1,
borderTopWidth: 1,
borderBottomWidth: 1,
flex: 1
},
waterContainer: {
borderLeftWidth: 1,
borderRightWidth: 1,
borderTopWidth: 1,
borderBottomWidth: 1,
flex: 1,
width: "100%",
},
timerContainer: {
borderLeftWidth: 1,
borderRightWidth: 1,
borderTopWidth: 1,
borderBottomWidth: 1,
flex: 2,
paddingBottom: 10,
},
titleText: {
paddingBottom: 5
},
subtitleText: {
paddingBottom: 20
},
statusTextWater: {
paddingBottom: 10
},
statusTextWR: {
paddingBottom: 20
}
});
and finally inside WaterIntake.jsx:
return (
<View style={styles.container}>
<Text category="h6" style={{paddingTop: 20, paddingBottom: 15}}>Water log</Text>
<View style={styles.buttonView}>
<Button style={styles.button} onPress={async () => {
await recordWaterIntake(0.25)
}} >1/4 Cup</Button>
<Button style={styles.button} onPress={async () => {
await recordWaterIntake(0.5)
}}> 1/2 Cup </Button>
<Button style={styles.button} onPress={async () => {
await recordWaterIntake(0.75)
}}> 3/4 Cup </Button>
<Button style={styles.button} onPress={async () => {
await recordWaterIntake(1)
}}> 1 Cup </Button>
</View>
<View style={styles.containerText}>
<Text>Total water consumed: {dayTotalWater}</Text>
<Button onPress={resetWaterDb}>Reset table</Button>
</View>
</View>
);
};
const styles = StyleSheet.create({
container: {
backgroundColor: "#fff",
justifyContent: "space-between"
},
buttonView: {
flex: 1,
flexDirection: "row",
width: "100%",
resizeMode: 'contain',
},
containerText: {
flex: 2,
flexDirection: 'column'
},
button: {
margin: 2,
// width:"22%",
}
});
Wrapping the buttonView div in flex: wrap
buttonView: {
flex: 1,
flexDirection: "row",
width: "100%",
resizeMode: 'contain',
flexWrap: 'wrap'
},
You can make it as a scrollable:
buttonView: {
flex: 1,
flexDirection: "row",
width: "100%",
resizeMode: 'contain',
overflow: 'auto'
},
Screenshot:

View to fit the screen in React Native

Hello there guys
i have a problem with CSS in react native, i want to fit all my components in the screen without ScrollView but i cant seem to figure out what is my problem(i tried to change values for margins or paddings but it will look different in every device.)
As you can see at the attached image:
As you can see the graph below is not in the screen, i need to scroll view to the graph(which i dont want)
here is the code + css : (I dropped some lines to shorten the code(Like the carousel components and etc)
<View style={{ backgroundColor: "#fff" , flex: 1 }}>
<LinearGradient
colors={["#4c669f", "#3b5998", "#192f6a"]}
start={[0, 0]}
end={[1, 0]}
>
<View style={{ marginHorizontal: 20, paddingVertical: 48 }}>
<View style={styles.imageContainer}>
<View>
<View style={styles.check}>
<Ionicons name="md-checkmark" size={20} color={colors.pink} />
</View>
<Image
source={require("../assets/profile-pic.jpeg")}
style={{
width: 100,
height: 100,
borderRadius: 32,
}}
/>
</View>
</View>
<View style={[styles.center, { marginVertical: 12 }]}>
<Text style={styles.title}>
{currentUser.name + " " + currentUser.lastName}
</Text>
<Text style={[styles.subTitle, { marginTop: 8 }]}>
{businessDetails.bussinesName}
</Text>
</View>
</View>
</LinearGradient>
<View style={styles.container}>
<View style={styles.statContainer}>
<Text style={styles.statNumber}>1,700₪</Text>
<Text style={styles.stat}>הכנסה חודשית תופיע כאן</Text>
</View>
</View>
<View style={styles.center}>
<Text style={styles.textGraphTitle}>Graphs Analysis:</Text>
</View>
<View>
</View>
</View>
);
CSS:
center: {
alignItems: "center",
justifyContent: "center",
},
imageContainer: {
alignItems: "center",
justifyContent: "center",
marginTop: 1,
shadowColor: colors.darkBg,
shadowOffset: { height: 3, width: 1 },
shadowOpacity: 0.5,
},
container: {
paddingVertical: 24,
paddingHorizontal: 32,
marginBottom: 8,
backgroundColor: colors.lightBg,
flexDirection: "row",
justifyContent: "space-between",
marginHorizontal: 16,
borderRadius: 16,
marginTop: -48,
},
statContainer: {
alignItems: "center",
justifyContent: "center",
flex: 1,
},
You are asking responsive app design. Basically, you can use for width and height percentages or dimension.
import { Dimensions} from 'react-native'
const {width, height} = Dimensions.get('window')
One more approach is to use react-native-screens library

Height of View in react native

Is it possible to make the <View /> having the same height? I am fetching a data from server side and some content are short and some are long. So when I display them in a box form, the height of the box aren't same. If I fix the height or minimum height the long text will exceed the height of the box.
EDIT : Sample code
DisplayEguides(){
var winsWidth = Dimensions.get('window').width;
if(this.state.eguides != null){
var eguides = this.state.eguides.map((data, i)=>(
<View key={i} style={[ { width: (60/100)*winsWidth, paddingHorizontal: 5 } ]}>
<TouchableOpacity
onPress={()=>this.OpenUrl(data.url)}
style={{ backgroundColor: '#ffffff', borderBottomWidth: 1, borderColor: '#efefef', elevation: 1, shadowOpacity: 0.8, marginBottom: 15, padding: 15, borderRadius: 15 }}>
<View style={{ alignItems: 'center', overflow: 'hidden', position: 'relative' }}>
<Text style={{ fontWeight: 'bold', textAlign: 'center', marginBottom: 15 }}>{ data.title }</Text>
<View style={{ flexDirection: 'row', alignItems: 'center', justifyContent: 'center' }}>
<Text style={{ color: Color.default, fontWeight: 'bold' }}>Download</Text>
<AntDesign name="download" size={16} color={Color.default} style={{ paddingLeft: 10, fontWeight: 'bold' }} />
</View>
</View>
</TouchableOpacity>
</View>
))
return (
<View style={{ paddingHorizontal: 15 }}>
<AppText type="bold" style={{ fontSize: 18, marginBottom: 15 }}>E-Guides</AppText>
<ScrollView horizontal={true} showsHorizontalScrollIndicator={false}>{ eguides }</ScrollView>
</View>
);
}
}
Seems like Flexbox in react native is doing the job but need to place at the right element. Setting the view to flex: 1 will auto adjust all content inside it to have the same height. In my case, I have to set flex: 1 at TouchableOpacity since my box style is in this element.
<TouchableOpacity
onPress={()=>this.OpenUrl(data.url)}
style={{ backgroundColor: '#ffffff', borderBottomWidth: 1, borderColor: '#efefef', elevation: 1, shadowOpacity: 0.8, marginBottom: 15, padding: 15, borderRadius: 15, flex: 1 }}>
{ /* The rest of code goes here */ }
</TouchableOpacity>

React Native shadow adds shadow to everything inside card

I am trying to generate a box shadow equivalent for React Native.
Here is my code:
<View style={{
shadowColor: "#000",
shadowOffset: {
width: 0,
height: 5,
},
shadowOpacity: 1,
shadowRadius: 5,
elevation: 5,
}}
>
<View styleName={"card promocard cardsize"} style={{
marginBottom: this.state.promoBottom, marginRight: this.state.promoRight,
}}>
<View styleName="promo-name" style={{ backgroundColor: this.rand }}>
<View styleName="promo-name-child">
<Image style={{ borderRadius: 50, resizeMode: "contain", backgroundColor: "#FFF" }} styleName="promocard-logo-img" source={{ url: this.props.promo.merchant.logo }} />
<Text style={{ color: "#fff" }} styleName="promo-name-text">{this.props.promo.merchant.name}</Text>
</View>
</View>
<View styleName="promo-inner-card">
<Image styleName="promo-main-img" source={{ url: this.props.promo.photo }} />
<View>
<View styleName="promo-title">
<Text styleName="promo-title-text">{this.props.promo.title}</Text>
</View>
<View styleName="promo-desc">
<Text styleName="promo-desc-text">{this.props.promo.text}</Text>
</View>
</View>
</View>
</View>
</View>
Rather than generate styles correctly around the rectangle (which is 330 by 175), it seems to apply the shadow to every element INSIDE the box.
I want something that looks like this:
https://ethercreative.github.io/react-native-shadow-generator/
I have been tearing my hair out, because every example I am seeing looks similar to the code I've got in my top level view, and yet I am getting shadows on all the text, and the images inside my view.
This was solved by adding a background color.
backgroundColor: "#FFF"

How can I mix fixed and dynamic size elements in a flexbox container?

I'm trying to create a layout that utilizes flexbox' automatic sizing but also contains fixed-size items:
<View style={{ height: 70, alignItems: "center" }}>
<Text style={{ flex: 1, textAlign: "right", paddingRight: 10 }}>left text</Text>
<Image style={{ width: 70, height: 70 }} src={require('./img.png')} />
<Text style={{ flex: 1, textAlign: "left", paddingLeft: 10 }}>right text</Text>
</View>
I want the image to be centered in the UI and have the text views equally take the remaining width. The actual result is that one of the text views is larger than the other as if the rendering doesn't take the width of the image view into account.
Finally found the correct way of doing this. To have fixed size items in a flex layout one shouldn't use width/height but flex: 0 and flexBasis. This approach initially didn't work for me because a component wrapping my component wasn't sized correctly and messed with the flex rendering. flexBasis seems to be density-independent pixels when it is set to an absolute number.
Proof of concept on expo.io
import React, { Component } from 'react';
import { Text, View, StyleSheet } from 'react-native';
import { Constants } from 'expo';
export default class App extends Component {
render() {
return (
<View>
<Text>Test</Text>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
<Text>Test</Text>
<View style={styles.container}>
<Text style={styles.text1}>{"Left\nText"}</Text>
<View style={styles.view} />
<Text style={styles.text2}>Test</Text>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flexDirection: "row",
alignItems: 'center',
justifyContent: 'center',
paddingTop: Constants.statusBarHeight,
backgroundColor: '#ecf0f1',
},
view: {
flex: 0,
flexBasis: 50,
height: 50,
backgroundColor: "red",
},
text1: {
flex: 1,
textAlign: "right",
paddingRight: 10,
},
text2: {
flex: 1,
textAlign: "left",
paddingLeft: 10,
}
});

Resources