How to display images in react native android app? - javascript

I want to images to take full width of device screen. I tried multiple CSS code but it doesn't take full width of screen.
Code:
<View style={styles.container}>
<View>
<Image source={require('./Images/rectangle/rectangle.png')} style={styles.backgroundImage}>
</Image>
</View>
</View>
const styles = StyleSheet.create({
container: {
flex: 1
},
backgroundImage: {
height: 200,
flexDirection: 'column',
alignSelf: 'stretch'
}
});
Above css doesn't work and I am getting white space on right side of image see screenshot:
I have also added images with different suffixes so that it will work for different screens see screenshot below:

try this:
backgroundImage:{
width: Dimension.get('window').width ,
alignSelf: 'center',
height: 200,
}

Related

react native ImageBackground not using full width

I have a Screen:
return (
<SafeAreaView style={styles.container}>
<ImageBackground source={require('../../../../assets/start.png')} resizeMode="cover" style={styles.image}>
<Text>Some Text</Text>
</ImageBackground>
</SafeAreaView>
);
And these are the styles I'm using:
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'white',
},
image: {
flex: 1,
justifyContent: 'center',
},
})
The problem is my background Image has white space around it.
From the above image you can see that the image has a gap at the top and the left side, it also has the same gap on the bottom and right.
Im trying to get this image edge to edge. Any idea?
iv tried adding 100% width and height and applying resize properties to the image, but its not working?

React native gesture passes through front view to the view behind

I am trying to make a react native app in which I have two views. One is above the behind (absolute) view.
I am using onStartShouldSetResponder to detect click outside the front view and I want to hide the login state.
But the gesture passes through front View to the view behind.
It means the login_component(below) click is also passed to login_container(below) and hides the view.
Here is my code,
<View onStartShouldSetResponder={() => true}
onResponderRelease={() => this.setState({ showLogin: false })}
style={styles.login_container}
>
<View onStartShouldSetResponder={() => false}
style={styles.login_component}
>
<Text>Join a room</Text>
</View>
</View>
Here is my styling code,
const styles = StyleSheet.create({
login_component: {
justifyContent: "center",
alignItems: "center",
height: 200,
width: 300,
backgroundColor: "#F5FCFF",
margin: "auto",
borderRadius: 15,
},
login_container: {
position: "absolute",
height: "100%",
width: "100%",
backgroundColor: "rgba(0,0,0,0.7)",
justifyContent: "center",
alignItems: "center",
},
});
Any idea how to fix this?
Here is a preview of what I am doing - https://i.imgur.com/KAhFAXX.png
Any alternate solution is also welcome.
Thank you
You can try setting a high "zIndex" CSS property for the JSX element that you want to be able to click. A higher zIndex will make sure that element is positioned above the one with the lower zIndex.
In your case, you want your "login_component" to be on top of "login_container". So your JSX can be modified as follows (not tested):
<View style={{...styles.login_container, zIndex: 99}}> // Lower zIndex (Below)
<View style={{...styles.login_component, zIndex: 999}}> // Higher zIndex (Above)
<Text>Join a room</Text>
</View>
</View>
Usually you wouldn't have to worry about setting zIndex yourself, but I'm guessing the 'position: "absolute"' property has affected the default behaviour.
Finally I got the solution it was simple just to use stopPropagation on the login_component.
Final code,
<View onStartShouldSetResponder={() => true}
onResponderRelease={() => this.setState({ showLogin: false })}
style={styles.login_container}
>
<View onStartShouldSetResponder={(e) => e.stopPropagation()}
style={styles.login_component}
>
<Text>Join a room</Text>
</View>
</View>

React Native: Why my text breaks like this and why is it not respecting the container margin?

I want to display multiple elements next to each other in React Native (with a flex wrap if there are too many elements or if the elements are too long). Each element consists of an icon and a text. If the text is too long, the text should break into the next line.
I tried different things with flexGrow and flexShrink but nothing had the desired effect. Here is my code (expo snack):
export default function App() {
function iconWithText(text) {
return (
<View style={styles.iconWithTextWrapper}>
<View style={{paddingRight: 10, backgroundColor: 'grey'}}>
<Text>Icon</Text>
</View>
<View style={{backgroundColor: 'yellow'}}>
<Text>{text}</Text>
</View>
</View>
)
}
return (
<View style={styles.container}>
{iconWithText('short text')}
{iconWithText('short text')}
{iconWithText('this is a long, long, long text that does break very ugly')}
</View>
);
}
const styles = StyleSheet.create({
container: {
marginTop: 50,
marginHorizontal: 50,
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
justifyContent: 'flex-start',
},
iconWithTextWrapper: {
flexDirection: 'row',
margin: 10,
}
});
Here is the corresponding result - as you can see the margin of the whole container is not respected and the text does not break very well:
Why is the right margin of the container not respected, why does the text break like this and how can I fix this?
Try adding a flex:1 to your text style.
edit:
I played around in your snack and came up with this:
https://snack.expo.io/#moistbobo/iconwithtext
Please see if this fits your use case.

React Native - Making background image avoid keyboard

I have a "fullscreen" background image that is used for a page:
container = {
flex: 1,
width: null,
height: null
}
<View ...>
...
<Image ... styles={container}>
...
<TextInput ... />
...
</Image>
</View>
However, as you may notice, tapping on the text input will open up the keyboard and the height of view changes. Since the image is set to cover, it also adjusts as the dimension of the view changes. I want the height of the parent view and the <Image> to not be affected by the keyboard, and only the content of the <Image> should be pushed up by the keyboard.
I'm aware there is a <KeyboardAvoidingView> available but I am not sure how to use it or does it even handle this situation.
Any ideas would be great. Thanks.
I do like this in React Native and it works :
backgroundImage: {
position: 'absolute',
left: 0,
top: 0,
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
},
I added
android:windowSoftInputMode="adjustPan"
to my AndroidManifest.xml and it worked out perfectly - the view doesn't get shrinked and the text inputs got pushed up.
Here's the solution I found to the same problem that I've faced. As you said, you can use react-native-keyboard-avoiding-view which is a really good way of avoiding keyboard and this solution implements that.
So what we have here is an image with style imageStyle wrapping everything.
render() {
return(
<Image source={{uri: 'blabla'}} style={imageStyle}>
<View style={styles.container}>
<KeyboardAwareScrollView>
<TouchableOpacity onPress={this.abc.bind(this)}>
<View style={styles.abc}>
<Text>Test</Text>
</View>
</TouchableOpacity>
...
</KeyboardAwareScrollView>
...
</View>
</Image>
)
}
and imageStyle:
const imageStyle = {
width: Dimensions.get('window').width,
height: Dimensions.get('window').height,
resizeMode: 'stretch',
}
Bonus: If you are going to support screen rotations, you can do:
const { width, height } = Dimensions.get('window')
const imageStyle = {
width: width < height ? width : height,
height: width < height ? height : width,
resizeMode: 'stretch',
}
Change
android:windowSoftInputMode="adjustResize"
To
android:windowSoftInputMode="adjustPan"
In android/app/src/main/AndroidManifest.xml, block activity
I wanted to accomplish the same thing, but without changing windowSoftInputMode.
I was able to do it by setting just the height of the image to Dimensions.get('window').height.
My background image stays put when the keyboard opens, but the components sitting on top of it move out of the way.
Because I was using React Navigation also, I was having issues using the window height effectively. I have a notification stuck to the bottom, and it was off the screen. My eventual solution was to close the ImageBackground element prior to the children:
<View style={styles.container}>
<ImageBackground
source={BACKGROUND}
imageStyle={{ resizeMode: 'repeat' }}
style={styles.imageBackground}
/>
<SafeAreaView style={{ flex: 1, justifyContent: 'space-between' }}>
<KeyboardAvoidingView behavior={Platform.OS === 'ios' ? "padding" : "height"} style={{flex: 1, justifyContent: 'space-between'}}>
{children}
</KeyboardAvoidingView>
<Notification/>
</SafeAreaView>
</View>
With styles looking like
export const { width: screenWidth, height: screenHeight } = Dimensions.get('window');
export const styles = StyleSheet.create(
{
notification: { position: 'absolute', bottom: 0, left: 0, right: 0, alignItems: 'stretch'},
imageBackground: { position: 'absolute', left: 0, top: 0, height: screenHeight, width: screenWidth },
container: {
flex: 1,
alignItems: 'stretch',
justifyContent: 'space-around',
},
});

React native flexbox - how to do percentages || columns || responsive || grid etc

After working with react native on iOS for the last couple of weeks, I seem to have come across some shortcomings of flex styling... Particularly when it comes to "responsive" behavior.
For instance, lets say you want to create a view that contains cards (the metadata for these cards comes from an API). You want the cards to be 50% of the view width minus the margin & padding, and to wrap after each 2.
The current implementation I have for this view splits the returned array into rows with 2 items. The list container has flex: 1, flexDirection: 'column, the rows have flex: 1 and then each card has flex: 1. The end result is each row has 2 columns which evenly take up half the view width.
It seems like there is no trivial way to do this in React Native styles, without using javascript to do some sort of pre-processing on the data so that it comes out styled correctly. Does anyone have any suggestions?
There may be a better way to achieve this with flexbox, but I usually define "percentage" helpers vw and vh for viewport width and viewport height, named after the CSS viewport size units of measurement:
import {Dimensions} from 'react-native';
function vw(percentageWidth) {
return Dimensions.get('window').width * (percentageWidth / 100);
}
function vh(percentageHeight) {
return Dimensions.get('window').height * (percentageHeight / 100);
}
To flow items in a grid, you can then calculate an appropriate size for items, accounting for margins and viewport size:
const COLUMNS = 3;
const MARGIN = vw(1);
const SPACING = (COLUMNS + 1) / COLUMNS * MARGIN;
const grid = {
flex: 1,
flexWrap: 'wrap',
flexDirection: 'row',
justifyContent: 'flex-start'
};
const cell = {
marginLeft: MARGIN,
marginTop: MARGIN,
width: vw(100) / COLUMNS - SPACING
}
return (
<View style={grid}>
{this.props.things.map(thing => <View style={cell} />)}
</View>
)
You should only use this technique if you have a known and limited number of items - for arbitrary amount of cards, you should use ListView for performance reasons, and split your data set to rows manually.
React Native already has percentage support:
<View style={[style.parent]}>
<View style={[style.child, {backgroundColor: '#996666'} ]} />
<View style={[style.child, {backgroundColor: '#339966'} ]} />
<View style={[style.child, {backgroundColor: '#996633'} ]} />
<View style={[style.child, {backgroundColor: '#669933'} ]} />
</View>
var style = StyleSheet.create({
parent: {
width: '100%',
flexDirection: 'row',
flexWrap: 'wrap'
},
child: {
width: '48%',
margin: '1%',
aspectRatio: 1,
}
})
You can use justifyContent: 'space-between'
<View style={styles.feed}>
<View style={styles.card} />
<View style={styles.card} />
<View style={styles.card} />
<View style={styles.card} />
</View>
feed: {
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
padding: 16,
justifyContent: 'space-between' }
card: {
backgroundColor: 'white',
width: '48%',
aspectRatio: 1,
marginBottom: 16 }
screenshot
This might solve this
<View style={{
flex: 1,
flexDirection: 'row',
flexWrap: 'wrap',
}}>
{array?.map((item, itemIndex) => {
return (
<View style={{
flexBasis: '50%',
height:OPTIONAL,
width:OPTIONAL
}}>
// YOUR CONTENT HERE
</View>
)
})}
</View>

Categories