Flexbox View does not wrap Image in React Native - react-native

When I have an Image inside a View with 'flex: 1' the View does not wrap the Image.
When I paste my code into react-native-web-player it works as expected..
The right image is what I expected, while the left is the actual result:
import * as React from 'react';
import { AppRegistry, View, Image, Text, StyleSheet } from 'react-native';
import SplitView from './components/SplitView';
function PurchaseLine() {
// tslint:disable-next-line:max-line-length
const imgUrl =
'https://cdn.shopify.com/s/files/1/0938/8938/products/10231100205_1_1315x1800_300_CMYK_1024x1024.jpeg?v=1445623369';
return (
<View style={styles.container}>
<Image source={{ uri: imgUrl }} style={styles.img} />
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
backgroundColor: 'red'
},
img: {
width: 45,
height: 62
}
});
export default class Datakasse extends React.Component<object, object> {
render() {
return (
<View>
<PurchaseLine />
</View>
);
}
}
AppRegistry.registerComponent('Datakasse', () => Datakasse);
UPDATE:
"height: 100%" or "flex: 1" on the outermost container, and not setting "flex: 1" on PurchaseLine's container seems to work.. Confused why I can't set the latter tho..
import * as React from 'react';
import { AppRegistry, View, Image, Text, StyleSheet } from 'react-native';
import SplitView from './components/SplitView';
function PurchaseLine() {
// tslint:disable-next-line:max-line-length
const imgUrl =
'https://cdn.shopify.com/s/files/1/0938/8938/products/10231100205_1_1315x1800_300_CMYK_1024x1024.jpeg?v=1445623369';
return (
<View style={styles.container}>
<Image source={{ uri: imgUrl }} style={styles.img} />
<Text>1 x Jacket</Text>
<Text>$99.99</Text>
</View>
);
}
const styles = StyleSheet.create({
container: {
backgroundColor: 'red',
flexDirection: 'row',
justifyContent: 'space-between',
alignItems: 'center',
padding: 10
},
img: {
width: 45,
height: 62
}
});
export default class Datakasse extends React.Component<object, object> {
render() {
return (
<View style={{ height: '100%', backgroundColor: 'blue' }}>
<PurchaseLine />
</View>
);
}
}
AppRegistry.registerComponent('Datakasse', () => Datakasse);

You can make use of a react-native "hack" and define the width as null like { width: null }. This will make it stretch at 100%. See also the example here based on your code
UPDATE:
the alignSelf what you are looking for. Sample here
UPDATE:
Try this example by setting flex on the parent element and remove from child. Your parent element wasnt defined as flex component so the child had issues. Check here
i removed the flex from container and added here
<View style={{flex: 1}}>

Related

React native layout misbehaving

I am trying to learn React native with Ignite. Been fighting with the layout.
Here is my main container render function:
render () {
return (
<View style={styles.mainContainer}>
<Image source={Images.background} style={styles.backgroundImage} resizeMode='stretch' />
<View style={[styles.container]}>
<View style={styles.section} >
{/* <Image source={Images.ready} />*/}
<Text style={styles.sectionText}>
Tap to randomly choose your training task. Slack off for 5
</Text>
</View>
<View style={styles.centered}>
<TouchableOpacity onPress={this._onPressButton}>
<Image source={Images.launch} style={styles.logo} />
</TouchableOpacity>
</View>
</View>
<View style={[styles.bottom]}>
<View >
<BottomBar />
</View>
</View>
</View>
)
}
In particular, the last sibling of the container has a view with a BottomBar component.The bottom style does this:
bottom: {
justifyContent: 'flex-end',
marginBottom: Metrics.baseMargin
}
the BottomBar component:
import React, { Component } from 'react'
// import PropTypes from 'prop-types';
import { View, Text, TouchableOpacity } from 'react-native'
import styles from './Styles/BottomBarStyle'
import Icon from 'react-native-vector-icons/FontAwesome'
export default class BottomBar extends Component {
// // Prop type warnings
// static propTypes = {
// someProperty: PropTypes.object,
// someSetting: PropTypes.bool.isRequired,
// }
//
// // Defaults for props
// static defaultProps = {
// someSetting: false
// }
render () {
console.tron.log('rendering my component')
console.tron.log('Bottom bar styles: \n',styles)
return (
<View style={[styles.iconsContainer, styles.debugGreen]}>
<TouchableOpacity style={[styles.icons,styles.debugYellow]} onPress={()=>{console.tron.log('rocket')}} >
<Icon style={styles.icons} name='rocket' size={40} color='white' />
</TouchableOpacity>
<TouchableOpacity style={styles.button} onPress={ ()=>{console.tron.log('send')} }>
<Icon style={styles.icons} name='send' size={40} color='white' />
</TouchableOpacity>
</View>
)
}
}
the styles associated with it:
import { StyleSheet } from 'react-native'
import DebugStyles from '../../Themes/DebugStyles'
import { Metrics } from '../../Themes/'
export default StyleSheet.create({
...DebugStyles,
iconsContainer: {
flex: 1,
flexDirection: 'row',
justifyContent: 'space-between',
height: 45,
borderRadius: 5,
marginHorizontal: Metrics.section,
marginVertical: Metrics.baseMargin
},
icons:{
height: 45
}
})
The issue I have, is that if I saw that bottomBar component for a Rounded button as such:
import React, { Component } from 'react'
import PropTypes from 'prop-types'
import { TouchableOpacity, Text } from 'react-native'
import styles from './Styles/RoundedButtonStyles'
import ExamplesRegistry from '../Services/ExamplesRegistry'
// Note that this file (App/Components/RoundedButton) needs to be
// imported in your app somewhere, otherwise your component won't be
// compiled and added to the examples dev screen.
// Ignore in coverage report
/* istanbul ignore next */
ExamplesRegistry.addComponentExample('Rounded Button', () =>
<RoundedButton
text='real buttons have curves'
onPress={() => window.alert('Rounded Button Pressed!')}
/>
)
console.tron.log('Rounded button style: ',styles)
export default class RoundedButton extends Component {
static propTypes = {
onPress: PropTypes.func,
text: PropTypes.string,
children: PropTypes.string,
navigator: PropTypes.object
}
getText () {
const buttonText = this.props.text || this.props.children || ''
return buttonText.toUpperCase()
}
render () {
console.tron.log('roundedButton styles:', styles)
return (
<TouchableOpacity style={styles.button} onPress={this.props.onPress}>
<Text style={styles.buttonText}>{this.getText()}</Text>
</TouchableOpacity>
)
}
}
with its styles:
import { StyleSheet } from 'react-native'
import { Fonts, Colors, Metrics } from '../../Themes/'
export default StyleSheet.create({
button: {
height: 45,
borderRadius: 5,
marginHorizontal: Metrics.section,
marginVertical: Metrics.baseMargin,
backgroundColor: Colors.fire,
justifyContent: 'center'
},
buttonText: {
color: Colors.snow,
textAlign: 'center',
fontWeight: 'bold',
fontSize: Fonts.size.medium,
marginVertical: Metrics.baseMargin
}
})
I get the expected view :
However, with my BottomBar component I get:
One thing to notice is that the debugGreen style is just a border that should wrap around my BottomBar component and it is shown flat, but the icons within it render lower, and the debugYellow styled box around the icon is shown around the icon as expected, just shifted a whole way down.
If your mainContainer's view is flex : 1 or height : 100%, you should divide the child's height by 8:2 or the flex by 8:2.
Example
<View style={styles.mainContainer}> // flex: 1
<View style={styles.container}> // flex : 0.8
...
</View>
<View style={styles.bottom}> // flex : 0.2
<BottomBar />
</View>
</View>

react-native-elements, button margin not taking effect

I had an issue where there was a white shadow above the button after applying the marginTop: 15 property.
This happens because buttonStyle applies styling to the inner View and since elevation (shadow) is applied to the outer View, this way you basically create a 'padding' in the outer View.
I was expecting for it to be resolved in the following manner as you see below:
import React, { Component } from "react";
import { View, Text, ScrollView, Dimensions } from "react-native";
import { Button } from "react-native-elements";
const SCREEN_WIDTH = Dimensions.get("window").width;
class Slides extends Component {
renderLastSlide(index) {
if (index === this.props.data.length - 1) {
return (
<Button
title="Onwards!"
raised
buttonStyle={styles.buttonStyle}
containerViewStyle={{ marginTop: 15 }}
onPress={this.props.onComplete}
/>
);
}
}
renderSlides() {
return this.props.data.map((slide, index) => {
return (
<View
key={slide.text}
style={[styles.slideStyle, { backgroundColor: slide.color }]}
>
<Text style={styles.textStyles}>{slide.text}</Text>
{this.renderLastSlide(index)}
</View>
);
});
}
render() {
return (
<ScrollView horizontal style={{ flex: 1 }} pagingEnabled>
{this.renderSlides()}
</ScrollView>
);
}
}
const styles = {
slideStyle: {
flex: 1,
justifyContent: "center",
alignItems: "center",
width: SCREEN_WIDTH
},
textStyles: {
fontSize: 30,
color: "white",
textAlign: "center"
},
buttonStyle: {
backgroundColor: "#0288D1"
}
};
export default Slides;
But the marginTop: 15 is having no effect on the button now. I am not sure what else to do here.
You can try View
<View style={{marginTop: 15}}}>
<Button
title="Onwards!"
raised
buttonStyle={styles.buttonStyle}
onPress={this.props.onComplete}
/>
<View>
Instead of using "style" to apply the style to the React Native Elements component, use containerStyle.
Here is the reference to the documentation where it is indicated:
https://reactnativeelements.com/docs/customization/
An example:
// A React Native Elements button
<Button
containerStyle={styles.button} // apply styles calling "containerStyle"
title="Sign up"
/>
// On the StyleSheet:
const styles = StyleSheet.create({
button: {
color: '#C830CC',
margin: 10,
},
});

I'm trying to load all the images as a scrollable menu but can't figure out how

I'm new to react native, I am trying to get a menu composed of logos that someone could just scroll down then tap one to go into more detail about it.
So I have my App.js file like so:
import React from 'react';
import {
StyleSheet,
View,
Image,
ScrollView,
Text
} from 'react-native';
import getImageForRestaurant from './utils/getImageForRestaurant';
import Avatar from './components/Avatar';
export default class App extends React.Component {
constructor(props) {
super(props);
this.state = {
restaurants: 'buffalo',
};
}
render() {
const {
restaurants
} = this.state;
return (
<View style={styles.appContainer}>
<View style={styles.titleContainer}>
<Text style={styles.title}>Title</Text>
</View>
<ScrollView style={styles.timerlist}>
<Avatar
initials="KC"
size={75}
source={getImageForRestaurant(restaurants)}
backgroundColor={'blue'}
onPressLinkImage={() => {
console.log('Pressed!');
}}
/>
</ScrollView>
</View>
);
}
}
const styles = StyleSheet.create({
appContainer: {
flex: 1,
justifyContent: 'center',
},
titleContainer: {
paddingTop: 35,
paddingBottom: 15,
borderBottomWidth: 1,
borderBottomColor: '#D6D7DA',
},
title: {
fontSize: 18,
fontWeight: 'bold',
textAlign: 'center',
},
timerList: {
paddingBottom: 15,
},
container: {
flex: 1,
backgroundColor: '#34495E',
},
imageContainer: {
flex: 0,
},
image: {
flex: 1,
width: 75,
height: 75,
resizeMode: 'contain',
},
});
The getImageForRestaurant() method works as intended if I make it inside an <Image/> but if I try to make it the source of my "Avatar" component then it won't work.
My getImageForRestaurant.js file is just this:
const images = {
buffalo1: require('../assets/restaurants/logo1.jpeg'),
buffalo: require('../assets/restaurants/logo2.png'),
buffalo2: require('../assets/restaurants/logo3.jpeg'),
};
export default restaurants => images[restaurants];
And finally my Avatar.js is as follows:
import {
ColorPropType,
StyleSheet,
Text,
View,
Image,
TouchableOpacity
} from 'react-native';
import PropTypes from 'prop-types';
import React from 'react';
import getImageForRestaurant from '../utils/getImageForRestaurant';
export default function Avatar({
size,
backgroundColor,
initials,
source,
onPressLinkImage,
}) {
const style = {
width: size,
height: size,
borderRadius: size / 2,
backgroundColor,
};
return (
<View style={[styles.container, style]}>
<TouchableOpacity onPress={onPressLinkImage}>
<Text style={styles.text}>{initials}</Text>
<Image source={require(getImageForRestaurant(source))} />
{/*<Image source={require("../assets/restaurants/logo1.jpeg")} />*/}
</TouchableOpacity>
</View>
);
}
Avatar.propTypes = {
initials: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
source: PropTypes.number.isRequired,
backgroundColor: ColorPropType.isRequired,
onPressLinkImage: PropTypes.func.isRequired,
};
const styles = StyleSheet.create({
container: {
alignItems: 'center',
justifyContent: 'center',
},
text: {
color: 'white',
},
});
So if I just do an Image source, (the commented part) it works as a regular image, but then I need to hard-code the actual url and what I want is to just load all images one next to the other in a scrollable grid. Haven't been able to figure out how to do what I want. Could someone please point me in the right direction?
While Edison makes a good point about good practices, I believe your problem is that you are just requiring the image twice. The output of the require() is what you need to pass to the Image component. You are doing require of a require.
<Image source={require(getImageForRestaurant(source))} />
Probably just changing to this should work:
<Image source={getImageForRestaurant(source)} />
It’s a bad practice to generate url inside the source prop. Always make sure that the necessary URL is built before its passed inside source prop. You can use a variable to build your URL and then pass it to source prop. (In your case, image is imported inside helper function and hence I will use image variable)
const image = getImageforRestaurant(source)
<Image source={image} />
When you want to load images from the internet do it like this.
const link = ‘http://example.com/image.png’
<Image source={{uri: link}} />

How to get the react native image to fit to the Image width and height

In the react-native Image I use, I set the width and height according to the dimensions of the screen. Now when I set an image source, the whole image is not displayed. I tried resizeMode and resizeMethod properties, but still it doesn't work properly. How can I achieve this?
import React, { Component } from "react";
import {
View,
Text,
Image,
Animated,
ScrollView,
StyleSheet,
Dimensions
} from "react-native";
import { PostProfileBar } from "../../component";
const width = Dimensions.get("window").width;
const height = Dimensions.get("window").height / 3;
class SharePostScreen extends Component {
constructor(props) {
super(props);
this.state = {
profile: {
avatar:
"https://img.bleacherreport.net/img/images/photos/003/733/498/hi-res-0579e42e6ee662e306e09bcf17d72dc4_crop_north.jpg?h=533&w=800&q=70&crop_x=center&crop_y=top",
first_name: "Sarah",
last_name: "Williams"
}
};
}
render() {
return (
<View style={styles.container}>
<View style={styles.sharePostWrapper}>
<ScrollView>
<PostProfileBar profile={this.state.profile} />
<Image
source={{
uri: "https://pbs.twimg.com/media/DWvRLbBVoAA4CCM.jpg"
}}
resizeMode={'cover'}
style={styles.image}
/>
</ScrollView>
</View>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1
},
sharePostWrapper: {
flex: 1,
margin: 5,
padding: 5,
borderWidth: 0.5,
borderColor: 'gray',
},
image: {
marginTop: 4,
width: width - 20,
height: height
}
});
export default SharePostScreen;
You need to use the Image in the following way
<Image
source={{
uri: "https://pbs.twimg.com/media/DWvRLbBVoAA4CCM.jpg"
}}
resizeMode={'stretch'}
style={styles.image}
/>
the resizeModes that you may require would be cover, stretch, repeat(IOS only)
To display the entire image, aspect ratio needs to be changed for most of the cases, therefore, you may use resizeMode: stretch

RN: Center spinner using flexbox?

I am trying to get as spinner centered vertically and horizontally (iOS and Android - currently testing on iOS). Here is my JSX
<View>
<Spinner/>
</View>
of course, Spinner is a custom component which is simply this that contains a ActivityIndicator
const Spinner = ({size}) => {
return (
<View style={styles.spinnerStyle}>
<ActivityIndicator/>
</View>
);
};
const styles = {
spinnerStyle: {
flex: 1,
justifyContent : 'center',
alignItems: 'center'
}
}
export {Spinner}
The spinner works but its always at the top of the screen, the spinner contains a VIEW and also the flex items that I think should work. But it doesn't
I also tried add some styles of the the first VIEW that holds the custom component ie..
<View style={....}>
<Spinner/>
</View>
But no joy.
I think you are almost there! The only thing that is missing is to set flex: 1 to the <View> around the <Spinner /> component.
I did create an example on Expo's Sketch. Feel free to have a look at it. Try removing the flex: 1 and add a background color to see how it behaves. Hope it helps!
import React, { Component } from 'react';
import { View, StyleSheet, ActivityIndicator } from 'react-native';
const spinnerStyles = StyleSheet.create({
spinnerStyle: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
},
});
class Spinner extends Component {
render() {
return (
<View style={spinnerStyles.spinnerStyle}>
<ActivityIndicator size="small" />
</View>
);
}
}
export default class App extends Component {
render() {
return (
<View style={styles.container}>
<Spinner />
</View>
);
}
}
const styles = StyleSheet.create({
container: {
flex: 1,
// backgroundColor: '#4286f4',
},
});