keeping image center after changing height - javascript

I have a simple page that opens an image with a few styles. However, when I change the height to say... height: SCREEN_HEIGHT - 200, the image gets smaller but does not remain center. Also, it might even be cutting out the image. How can I fix this so I can make the image smaller but remain center?
If I give it a height: 100 and a width: 100, and position it with absolute or justify content, will it look the same across all devices?
Thank you guys for any input at all! I appreciate it more than you know.
import React from'react'
import { StyleSheet, Text, View, Dimensions, Image, Animated} from 'react-native'
const SCREEN_HEIGHT = Dimensions.get('window').height
const SCREEN_WIDTH = Dimensions.get('window').width
const Bars = [
{id : "1", uri: require('./assets/placeholder1.jpg')},
{id : "2", uri: require('./assets/placeholder2.jpg')},
{id : "3", uri: require('./assets/placeholder3.jpg')},
{id : "4", uri: require('./assets/placeholder4.jpg')},
{id : "5", uri: require('./assets/placeholder5.jpg')},
{id : "6", uri: require('./assets/placeholder6.jpg')},
{id : "7", uri: require('./assets/placeholder7.jpg')},
{id : "8", uri: require('./assets/placeholder8.jpg')},
{id : "9", uri: require('./assets/placeholder9.jpg')},
]
export default class App extends React.Component {
render() {
return(
<View style={{flex:1}}>
{/* styles header */}
<View style={{height: 60 }}>
</View>
{/* styles bar images */}
<View style={{flex: 1}}>
<Animated.View style={styles.barImage}>
<Image
style={{flex: 1 ,
height: null,
width: null,
borderRadius: 20
}}
resizeMode='cover'
source={Bars[0].uri} />
</Animated.View>
</View>
{/* styles footer if I even need it */}
<View style={{height: 60 }}>
</View>
</View>
)
}
}
const styles = StyleSheet.create({
barImage: {
height: SCREEN_HEIGHT - 170,
width:SCREEN_WIDTH,
padding: 10,
}
}
)

You are using resizeMode wrong. resizeMode is a prop of the <Image /> component. You have to wrap the <Image /> with a <View /> and give that <View /> a width and height and center that <View />.
<View style={{alignItems: 'center', justifyContent: 'center'}}>
<View style={{width: 100, height: 100}}>
<Image
...
resizeMode='cover'
...
/>
</View>
</View>

In your stylesheet, use the margin elements to center the image. If you set them to auto, it'll center them automatically. You can also use vertical-align and many other center components. Use this website for more context and better understanding with multiple other ways to suit your use case : https://www.w3.org/Style/Examples/007/center.en.html

Related

React Native - How to set width of Views inside ScrollView to fit?

I have multiple Views inside my horizontal ScrollView. How can I set them such that each of those views has the exact dimensions as that of the ScrollView?
I want to use paging and go to my next View inside the ScrollView on swiping. I have tried to use width : "100%" but it does not work as ScrollView does not have fixed dimensions, but that is basically what I want to do with the views inside it. Here is my code:
export default class HorizontalScrollView extends Component {
render () {
screenWidth = "100%"
return (
<ScrollView
contentContainerStyle={styles.scrollable}
horizontal={true}
snapToInterval={screenWidth}
decelerationRate={"fast"}
>
<View style={StyleSheet.compose(styles.insideContainer, {"width" : screenWidth, "backgroundColor" : "red"})}>
<Text>Screen 1</Text>
</View>
<View style={StyleSheet.compose(styles.insideContainer, {"width" : screenWidth, "backgroundColor" : "blue"})}>
<Text>Screen 3</Text>
</View>
<View style={StyleSheet.compose(styles.insideContainer, {"width" : screenWidth, "backgroundColor" : "green"})}>
<Text>Screen 2</Text>
</View>
</
StyleSheet:
styles = StyleSheet.create({
"scrollable" : {
"backgroundColor" : "black",
"height" : "100%"
},
"insideContainer" : {
"alignItems" : "center",
"justifyContent" : "center",
"flex" : 1,
}
})
P.S. - I am using an Android Samsung Galaxy M30 to test this.
Any help or explanation would be appreciated.
Thank you.
Based on your code use these styles to accomplish what you want
<ScrollView horizontal={true} snapToInterval={Dimensions.get('screen').width} contentContainerStyle={{minHeight: '100%'}}>
<View style={{flexDirection: 'row'}}>
<View style={{width: Dimensions.get('screen').width, height: Dimensions.get('screen').height, backgroundColor: 'green'}}>
<Text>Screen 1</Text>
</View>
<View style={{width: Dimensions.get('screen').width, height: Dimensions.get('screen').height, backgroundColor: 'red'}}>
<Text>Screen 2</Text>
</View>
<View style={{width: Dimensions.get('screen').width, height: Dimensions.get('screen').height, backgroundColor: 'yellow'}}>
<Text>Screen 3</Text>
</View>
</View>
</ScrollView>
If your scroll view is the width of the screen, you can set each view inside to have a width of
Dimensions.get(“screen”).width
Then set the pagingEnabled prop of the ScrollView to true and you should have a paging scroller with full width sub views.

crop an image of icons

I just want to know how to display a part of an image in react-native
class InstaClone extends Component {
render() {
return(
<View style={{ flex:1, width:100 + "%", height:100 + "%" }}>
<View style={styles.TopNavStyle}>
<Text style={styles.TopNavTextStyle}>
Instagram
</Text>
</View>
<View style = {styles.userBar}>
<View style = {{ flexDirection:"row" , alignItems:"center" }}>
<Image style = {styles.userPic}
source = {require('../assets/images/photoUser.jpg')}/>
<Text style = {{marginLeft : 10}}>
Mohcouch
</Text>
</View>
<View>
<View style={styles.imageContainer}>
<ImageBackground
source={require('../assets/images/icons.jpg')}
style={styles.image}
></ImageBackground>
</View>
</View>
</View>
<Image
style={{ width:"100%", height:400 }}
source={require('../assets/images/baby.jpg')}
/>
</View>
)
}
}
} , image: {
height: 500,
width: 500,
resizeMode:"cover",
translateX:-80,
translateY: -135,
},
imageContainer: {
height: 40,
backgroundColor:'transparent',
width: 40,
},
})
export default InstaClone
Result :
https://scontent.xx.fbcdn.net/v/t1.15752-0/p280x280/58461695_2231014486986604_1022634010985103360_n.png?_nc_cat=102&_nc_ad=z-m&_nc_cid=0&_nc_zor=9&_nc_ht=scontent.xx&oh=cb81348aae1c524ba9e93d1e02afb120&oe=5D44DF9C
the image of icons :
https://scontent.xx.fbcdn.net/v/t1.15752-0/p280x280/51865955_790216374668323_1242853141917990912_n.jpg?_nc_cat=102&_nc_ad=z-m&_nc_cid=0&_nc_zor=9&_nc_ht=scontent.xx&oh=1c6d18d17e24ec68771be2590fc934c4&oe=5D2CC871
React Native doesn's support a property background-position. It is better to separate the icons in different image files.
But there is a tricky workaround that you can use with your sprite image:
First, you need to round the image pixels in layout size (dp):
const width = PixelRatio.roundToNearestPixel(280);
const height = PixelRatio.roundToNearestPixel(280);
Note: 280 is the size of the image from your post
Then, we need to calculate the same proportion for the size of the icon:
const iconWidth = PixelRatio.roundToNearestPixel(30);
const iconHeight = PixelRatio.roundToNearestPixel(30);
Note: 30 is a random size for our icon, it can be any size.
Now, for the loading of the image, we will use the ImageBackground component from react-native. For imageStyle we will pass the positioning properties of the image:
imageStyle={{
resizeMode: 'cover',
width: width, height: height,
top: -15,
left: -15
}}
Your component should look like this:
<ImageBackground
source={{ uri: image_url }}
style={{ width: iconWidth, height: iconHeight, overflow: 'hidden' }}
imageStyle={{
resizeMode: 'cover',
width: width, height: height,
top: -15,
left: -15
}}
/>
Here is a working demo.

"The <Image> component cannot contain children " in React Native, Possible fix ?

Day 1 with React-Native . Trying to load multiple images in a React-Native app. However, the app crashes with the error:
Error: The component cannot contain children. If you want to
render content on top of the image, consider using the
<ImageBackground> component or absolute positioning.
I tried solutions to these existing questions, however they failed to resolve my issue:
How to use ImageBackground to set background image for screen in react-native.
Tile component issues with latest react 0.50.0 #709
Also tried replacing <ImageBackground> with <Image>, however that did not resolve the issue as well.
Here's the code to my App.js :
import React, { Component } from 'react';
import {
StyleSheet,
View,
Image
} from 'react-native';
const playIcon = require('./images/play.png');
const volumeIcon = require('./images/sound.png');
const hdIcon = require('./images/hd-sign.png');
const fullScreenIcon = require('./images/full-screen.png');
const remoteImage = { uri:'https://s3.amazonaws.com/crysfel/public/book/new-york.jpg' };
export default class App extends Component<{}> {
render() {
return (
<Image source={remoteImage} style={styles.fullscreen}>
<View style={styles.container}>
<Image source={playIcon} style={styles.icon} />
<Image source={volumeIcon} style={styles.icon} />
<View style={styles.progress}>
<View style={styles.progressBar} />
</View>
<Image source={hdIcon} style={styles.icon} />
<Image source={fullScreenIcon} style={styles.icon} />
</View>
</Image>
);
}
}
const styles = StyleSheet.create({
fullscreen: {
flex: 1,
},
container: {
position: 'absolute',
backgroundColor: '#202020',
borderRadius: 5,
flexDirection: 'row',
height: 50,
padding: 5,
paddingTop: 16,
bottom: 30,
right: 10,
left: 10,
borderWidth: 1,
borderColor: '#303030',
},
icon: {
tintColor: '#fff',
height: 16,
width: 16,
marginLeft: 5,
marginRight: 5,
},
progress: {
backgroundColor: '#000',
borderRadius: 7,
flex: 1,
height: 14,
margin: 10,
marginTop: 2,
},
progressBar: {
backgroundColor: '#bf161c',
borderRadius: 5,
height: 10,
margin: 2,
width: 80,
},
});
What is possibly causing this issue and how to resolve it?
<Image> with nested content is no longer supported. Use <ImageBackground> instead.
<View style={styles}>
<ImageBackground style={styles} source={source} resizeMode={resizeMode} >
{children}
</ImageBackground>
{...}
</View>
Also you need to add a parent component (View) to wrap all your components.
It's not work because you must wrap all your components with parent View.
Image cannot be the parent view.
something like this:
render() {
return (
<View>
<Image source={remoteImage} style={styles.fullscreen}>
<View style={styles.container}>
<Image source={playIcon} style={styles.icon} />
<Image source={volumeIcon} style={styles.icon} />
<View style={styles.progress}>
<View style={styles.progressBar} />
</View>
<Image source={hdIcon} style={styles.icon} />
<Image source={fullScreenIcon} style={styles.icon} />
</View>
</Image>
</View>
);
}

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',
},
});

2 Different Background Colours For ScrollView bounce

I have a ScrollView that has a top section with one background colour and a bottom section with another different colour.
When a user scrolls past the content and the view bounces (elastic over-extend), how could I make it so the background is consistent with either the top or the bottom, depending on the scroll direction?
I wouldn't play with the contentInset and contentOffset of the ScrollView as if your content changes, it might change the position of your scrollview.
You can do something very simple by just adding a View at the very top of your ScrollView:
// const spacerHeight = 1000;
<ScrollView>
{Platform.OS === 'ios' && (
<View
style={{
backgroundColor: 'red',
height: spacerHeight,
position: 'absolute',
top: -spacerHeight,
left: 0,
right: 0,
}}
/>
)}
</ScrollView>
On iOS, you can render a spacer View on top of the ScrollView, and use contentInset to render it "off-screen", contentOffset to set the initial scroll position to offset the inset:
render() {
const isIos = Platform.OS === 'ios'
const SPACER_SIZE = 1000; //arbitrary size
const TOP_COLOR = 'white';
const BOTTOM_COLOR = 'papayawhip';
return (
<ScrollView
style={{backgroundColor: isIos ? BOTTOM_COLOR : TOP_COLOR }}
contentContainerStyle={{backgroundColor: TOP_COLOR}}
contentInset={{top: -SPACER_SIZE}}
contentOffset={{y: SPACER_SIZE}}>
{isIos && <View style={{height: SPACER_SIZE}} />}
//...your content here
</ScrollView>
);
}
Because contentInset and contentOffset are iOS only, this example is conditioned to degrade gracefully on Android.
The accepted solution did not work well for me because I need to put flexGrow: 1 on the contentContainerStyle. Using insets/offsets didn't make the content grow the way I want, otherwise it worked not so bad.
I have another solution to suggest: putting a bicolor background layer under a transparent ScrollView, and add colors to your scrollview content. This way, on ios bounce, the bicolor layer under the scrollview will reveal itself.
Here's what I mean by bicolor layer (here the scrollview is empty and transparent)
Now if I put back the ScrollView children (which if a body with blank background, and a footer with yellow background), I get this:
As long as you don't bounce more than 50% of the scrollview height, you will see the appropriate background color.
Here's a component you can use to wrap your scrollview.
const AppScrollViewIOSBounceColorsWrapper = ({
topBounceColor,
bottomBounceColor,
children,
...props
}) => {
return (
<View {...props} style={[{ position: 'relative' }, props.style]}>
{children}
<View
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: -1, // appear under the scrollview
}}
>
<View
style={{ flex: 1, backgroundColor: topBounceColor }}
/>
<View
style={{ flex: 1, backgroundColor: bottomBounceColor }}
/>
</View>
</View>
);
};
And here's how you use it:
<AppScrollViewIOSBounceColorsWrapper
style={{flex: 1}}
topBounceColor="white"
bottomBounceColor="yellowLancey"
>
<ScrollView style={{flex: 1}}>
<WhiteBackgroundBody/>
<YellowBackgroundFooter />
</AppScrollView>
</AppScrollViewIOSBounceColorsWrapper>
Make sure to NOT set a background color to the scrollview, otherwise the bicolor layer will never reveal itself (backgroundColor on contentContainerStyle is fine)
This is, I think the most stupid simple way i found to do it:
<ScrollView style={{backgroundColor: '#000000'}}>
[...]
<View style={{position: "absolute", bottom: -600, left: 0, right: 0, backgroundColor: '#FFFFFF', height: 600}}/>
</ScrollView>
You may adjust the height/bottom absolute value to your likings depending on how far you think the user could scroll.
I personally implemented that into a <ScrollBottom color={"white"}/> component for ease of use in all my ScrollViews
For me, the simplest solution is modification based on Sebastien Lorber answer which doesn't include wrapping, just calling it before (or after) ScrollView component:
Create component:
interface IScrollViewBackgroundLayer {
topBounceColor: string;
bottomBounceColor: string;
}
export const ScrollViewBackgroundLayer = ({
topBounceColor,
bottomBounceColor,
}: IScrollViewBackgroundLayer): ReactElement => (
<View
style={{
position: 'absolute',
top: 0,
left: 0,
width: '100%',
height: '100%',
zIndex: -1, // appear under the scrollview
}}>
<View style={{ flex: 1, backgroundColor: topBounceColor }} />
<View style={{ flex: 1, backgroundColor: bottomBounceColor }} />
</View>
);
and use it like this:
return (
<SafeAreaView style={styles.container}>
<ScrollViewBackgroundLayer topBounceColor={topBounceColor} bottomBounceColor={bottomBounceColor} />
<ScrollView>
...
</ScrollView>
</SafeAreaView>

Categories