I have code that looks like this:
<View style={styles.logoContainer}>
<View style={styles.logoTextContainer}>
<Text style={styles.logoText}>{siteName}</Text>
</View>
<View style={styles.logoImageContainer}>
<Image source={logo} style={styles.logo} resizeMode="contain" />
</View>
</View>
With the relevant styles looking like this:
logoContainer: {
flex: 4,
alignSelf: 'stretch',
alignItems: 'center',
justifyContent: 'space-evenly',
// borderWidth: 1,
// borderColor: 'blue',
},
logoImageContainer: {
flex: 3,
justifyContent: 'center',
// borderWidth: 1,
// borderColor: 'red',
},
logo: {
width: 250,
height: 250,
},
The issue is that the (square) image does not scale to fit inside the container (the commented out borders are so that I can make sure the containers are where I think they are, and the right size - they are).
I have seen various questions about this - some concern remote images, not the case here. Other suggestions:
Set resizeMode as a prop to the Image element.
Set resizeMode as a style.
Do either of the above with the width as 'undefined' in the style.
Do either of the above with the width as 'auto' in the style.
None have made any difference, the only thing that works is setting width and height specifically, as seen in the code above. This looks ok on the more recent (read: larger) iPhone sims, but causes the image to overlap with other stuff on the iPhone 5 sim.
To check if the resizeMode prop is having any effect, I set it to 'center' (with no width or height styles). This was a bit more promising, as the image is now only slightly wider than the screen. However, it is still much taller than the view, which contradicts the docs on resizeMode: center:
center: Center the image in the view along both dimensions. If the
image is larger than the view, scale it down uniformly so that it is
contained in the view.
Trying to add width=auto/undefined to resizeMode="center", causes the image not to display at all.
The logoImageContainer is a defined size (defined through flexbox), and I just want the image scaled and centred to fit in it.
Related
I have the following image in my React Native app
I want to have this image inside a parent element with no space above or below it, and I want the image to not overshoot the left or right sides of the screen
When I have the code like this
<View style={{
marginTop: 100,
borderWidth: 2,
borderColor: 'red'
}}>
<Image
style={{
width: '100%'
}}
source={require('#images/swoosh-02.png')}
/>
</View>
I get this, because default for resizeMode is cover
When I change it to this (adding resizeMode='contain')
<View style={{
marginTop: 100,
borderWidth: 2,
borderColor: 'red'
}}>
<Image
style={{
width: '100%'
}}
resizeMode='contain'
source={require('#images/swoosh-02.png')}
/>
</View>
the image gets successfully contained horizontally, but the height of the parent element remains the same as it was when resizeMode was cover.
How can I get it so that the parent element shrinks vertically to contain only the image and not have that extra top/bottom padding?
De diference between contain and cover is :
resizeMode='contain' = Scale the image uniformly (maintain the image’s aspect ratio) so that both dimensions (width and height) of the image will be equal to or less than the corresponding dimension of the view (minus padding).
resizeMode='cover' = Scale the image uniformly (maintain the image’s aspect ratio) so that both dimensions (width and height) of the image will be equal to or larger than the corresponding dimension of the view (minus padding).
Maybe you should try to apply height in your View.
Read this article, should help you.
I have a certain problem that I am facing and would like to see whether or not what I am facing is a react-native bug that needs submission to the react-native issues or if it is an error on my part.
I am trying to create a TextInput that is centered to my screen and is supposed to be able to grow in width as one types into it, once enough text is written it wraps to the next line. I am facing a problem that as one types in the TextInput the text appears first and then changes the size of the view causing a flicker and words typed to disappear and then reappear. Eventually the UI settles correctly and appears correct, but as one types the previous written characters can flow to be greater than the width of the View despite the View has no limit to width. I know I have figured out this is due to the parent have a alignItems property that makes the children (in this case the TextInput) centered.
The goal is to make the view expanded in width along side the text being written without this flickering bug.
return (
<KeyboardAvoidingView behavior="height" keyboardVerticalOffset={Platform.OS === 'ios' > 0 : 24} style={styles.flex1}>
<View style={styles.addingText}>
<TextInput
multiline
returnKeyType="done"
blurOnSubmit={true}
textAlignVertical="center"
style={styles.defaultAddingText}
autoFocus={addingText}
selectionColor="#3C99FF"
underlineColorAndroid="transparent"
value={text}
onChangeText={handleTextChange}
onSubmitEditing={handleSubmit}
/>
</View>
</KeyboardAvoidingView>
);
const styles = StyleSheet.create({
flex1: {
flex: 1,
},
addingText: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
zIndex: 100,
},
defaultAddingText: {
paddingHorizontal: 10,
borderRadius: 10,
},
});
Give a height to your defalutAddingText style as following,
const styles = StyleSheet.create({
flex1: {
flex: 1,
},
addingText: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
zIndex: 100,
},
defaultAddingText: {
height:auto,
paddingHorizontal: 10,
borderRadius: 10,
},
});
In my React Native app, I have a red box of height 300 that I want to center vertically, and an image that I want to sit inside and at the top of this red box. Here is my code so far:
import React, { Component } from 'react';
import { View, Image} from 'react-native';
export default class Login extends Component {
render() {
return (
<View style={{
flex: 1,
justifyContent: "center",
alignItems: "center"
}}>
<View
style={{
borderWidth: 3,
borderColor: 'red',
width: "100%",
height: 300
}}
>
<Image
source={require('../../images/swoord-top.png')}
style={{
width: "100%",
height: "100%",
resizeMode: "contain",
borderWidth: 3
}}
>
</Image>
</View>
</View>
);
}
}
Here's what this looks like:
The red box is the outer box I mentioned, and the black box is just the border of the Image. The problem is that this black box (ie the Image) expands to fill the red box vertically, and the image is vertically centered inside this black box, so it's vertically centered inside the red box, as opposed to at the flex-start position that I want it at. I've tried adding justifyContent: flex-start and flexShrink: 1 to the Image and neither has made a difference.
Does anyone know how I can approach this?
NOTE:
If I remove the height: 100% on the Image, I get this:
UPDATE:
To clarify, this is what I'd like it to look like. I've removed the black border here. I moved it up to where I want it by adding top: -95, but this won't work in general because the value would be different for different devices:
try doing like this
<Image
source={require('../../images/swoord-top.png')}
style={{
width: "100%",
borderWidth: 3
}}
resizeMode={"contain"}
/>
There is a difference between Image (the view) and the content of that image. On your screenshot, the image view has the black border and its content is sitting inside of it. Because they have different aspect ratios, there is going to be either a blank space or cut-off on the content. You can't adjust position of the content as it's not laid out on flex basis. Image view is just a window that then renders image content. There is no property to tell Image where to align that content
Your problem comes from the fact that screen width differs, and aspect ratio of your container also differs (variable width but constant 300 height). What you need to do is
measure container width
determine proper aspect ratio for the image based on image resource width and height
set your image width to 100% and its height according to received aspect ratio
here, my image dimensions are 1005 * 219:
const Test = () => {
const [width, setWidth] = useState(0);
return (
<View>
<View
onLayout={e => setWidth(e.nativeEvent.layout.width)}
style={{ width: '100%', height: 300, borderWidth: 1 }}>
<Image
style={{
width: '100%',
height: (width / 1005) * 219,
borderWidth: 1,
borderColor: 'red',
}}
source={require('...')}
/>
</View>
</View>
);
};
I'd like to achieve a layout with Flexbox in React Native. The idea is to be able to have a responsive image with text beneath it, vertically centered in on the page.
The issue seems that the View that contains the image, either ends up disappearing as the image has no height or filling the entire screen height and pushing the text that shoud be below the image down to the bottom.
I assume its to do with the image dimensions being undefined in order to get it to act in a responsive way and fill the parent container.
Here's a mockup of the layout
Update
Thanks Topik Mujianto - I was actually following that very tutorial!
Here's my code:
const styles = StyleSheet.create({
pageContainer: {
flex: 1,
flexDirection:'row',
justifyContent:'center',
backgroundColor: "blue",
alignItems: 'flex-start'
},
columnStyle: {
flex: 0.7,
flexDirection:'column',
backgroundColor: "red",
borderWidth: 1,
alignItems: 'flex-start'
},
imgStyle: {
flex: 1,
height: undefined,
width: undefined,
alignSelf: 'stretch',
}
})
const Component = props => (
<View style={styles.pageContainer}>
<View style={styles.columnStyle}>
<Image
style={styles.imgStyle}
resizeMode="contain"
source={require('../../../assets/images/onboarding-how-it-works.png')}
/>
</View>
</View>
);
Which gives this:
Centered on page
But if I try to get the image to align top with this code:
imgStyle: {
flex: 1,
height: undefined,
width: undefined,
alignSelf: 'felx-start',
}
I get this (the image has disappeared):
No image
After a bit more investigation I can see that acutally the image is stretching to fit as it has the flex: 1 property. I set the background colour to yellow on the image and get this:
Image background shows size of image box
So the question is, how do I get the image to be responsive without its container stretching to the parent and shrinking to fit the responsive image content, and then align it to the top?
How react native Text and Image responsive?
I only know the Flexbox can make layout responsive but seems can not apply in text and image.
e.g.Make my text and image smaller in iphone 4s, bigger in iphone 6
Thanks.
You can use Flexbox in order to make your application responsive.
For example, say you wanted to display a line of text and an image on the same line:
class ResponsiveExample extends Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.text}>
Example of centered text
</Text>
<Image
resizeMode={"contain"}
style={styles.image}
source={{uri: "your image"}}/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
flexDirection: "row",
alignItems: "center",
justifyContent: "space-between"
},
text: {
marginLeft: 20,
flex: 1
},
image: {
marginRight: 20,
height: 400,
flex: 3,
}
});
Now the text and image will be displayed relative to the screen size. The usual hangup here is that flexDirection defaults to column, which will make things line up vertically. You can see what happens when we flip from portrait to landscape orientation:
As you can see, the text and image respond to the change in orientation.
For a better overview of Flexbox, I like to refer to the following guide:
https://css-tricks.com/snippets/css/a-guide-to-flexbox/.
Just keep in mind that React Native defaults to a flex-direction of column, so if you want things laid out horizontally, you'll have to explicitly set it to row.
I think react-native-fit-image is useful for you.
React Native Fit Image enables you to draw responsive image component.
You can use this component as below.
<FitImage
source={{ uri: 'http://facebook.github.io/react/img/logo_og.png' }}
style={styles.fitImage}
/>
You are right to think about Flexbox, simply wrap your Text and Image inside View and make those View flexbox responsive.