I tried both absolute and flex dimensions, the View just sets the Button at standard dimensions (approx 50px). The height is stretched, but the width can't possibly change.
class Calculator extends Component {
constructor() {
super();
this.state = { "lastClicked" : "None" };
this.buttonPress = this.buttonPress.bind(this);
}
createButton(id) {
return (
<Button
title={id}
onPress={() => this.buttonPress(id)}
/>
);
}
buttonPress(id) {
this.setState({ "lastClicked" : id });
}
render() {
return (
<View style={{alignContent: "stretch"}}>
<View style={{width: 500}}>
<Text style={{fontSize: 30}}>This is a JavaScript Calculator</Text>
<Text style={{fontSize: 20}}>You clicked: {this.state.lastClicked}</Text>
</View>
<View style={{width: 500}}>
<View style={{ width: 500, height: 150, flexDirection : "row", alignItems: "stretch", alignContent: "stretch", alignSelf: "stretch"}}>
{this.createButton("4")}
{this.createButton("5")}
{this.createButton("6")}
</View>
<View style={{ width: 500, height: 150, flexDirection : "row", alignItems: "stretch", alignContent: "stretch", alignSelf: "stretch"}}>
{this.createButton("4")}
{this.createButton("5")}
{this.createButton("6")}
</View>
<View style={{ width: 500, height: 150, flexDirection : "row", alignItems: "stretch", alignContent: "stretch", alignSelf: "stretch"}}>
{this.createButton("1")}
{this.createButton("2")}
{this.createButton("3")}
</View>
</View>
</View>
);
}
}
}
Can you see the issue? I am new to React-Native and the issue already consumed 3 hours of my life.
You can replace the createButton() method with something like that:
createButton(id) {
return (
<TouchableWithoutFeedback onPress={() => this.buttonPress(id)}>
<View style={{flex: 3, flexDirection:'column', justifyContent:'center', alignItems:'center'}}>
<Text style={{fontSize:30}}>{id}</Text>
</View>
</TouchableWithoutFeedback>
);
}
I wrapped a <View> with style flex: 3 for setting the width to a third of the screen size. flexDirection:'column' and justifyContent:'center' will center the number in the middle of the View. The View is wrapped in a TouchableWithoutFeedback so that we can bind the onPress event.
For your grid of numbers, you wrapped then in <View style={{width: 500}}>. This is not always the size of the screen. It's easy to get the screen width using Dimensions.
At the start of your file, you can declare something like:
const screenWidth = Dimensions.get('window');
And then replace <View style={{width: 500}}> by <View style={{width: screenWidth}}>.
Overall, your new code should look like:
import React, { Component } from 'react';
import { Text, View, Dimensions, TouchableWithoutFeedback } from 'react-native';
const screenWidth = Dimensions.get('window');
export default class App extends Component {
constructor() {
super();
this.state = { "lastClicked" : "None" };
this.buttonPress = this.buttonPress.bind(this);
}
createButton(id) {
return (
<TouchableWithoutFeedback onPress={() => this.buttonPress(id)}>
<View style={{flex: 3, justifyContent:'center', alignItems:'center'}}>
<Text style={{fontSize:30}}>{id}</Text>
</View>
</TouchableWithoutFeedback>
);
}
buttonPress(id) {
this.setState({ "lastClicked" : id });
}
render() {
return (
<View style={{alignContent: "stretch"}}>
<View style={{width: screenWidth}}>
<Text style={{fontSize: 30}}>This is a JavaScript Calculator</Text>
<Text style={{fontSize: 20}}>You clicked: {this.state.lastClicked}</Text>
</View>
<View style={{width:screenWidth}}>
<View style={{height: 150, flexDirection : "row", alignItems: "stretch", alignContent: "stretch", alignSelf: "stretch",}}>
{this.createButton("7")}
{this.createButton("8")}
{this.createButton("9")}
</View>
<View style={{height: 150, flexDirection : "row", alignItems: "stretch", alignContent: "stretch", alignSelf: "stretch"}}>
{this.createButton("4")}
{this.createButton("5")}
{this.createButton("6")}
</View>
<View style={{height: 150, flexDirection : "row", alignItems: "stretch", alignContent: "stretch", alignSelf: "stretch"}}>
{this.createButton("1")}
{this.createButton("2")}
{this.createButton("3")}
</View>
</View>
</View>
);
}
}
Demo on snack.expo.io
Related
I was making an app and added text on HomeScreen. I am getting the text in Web but am not able to get it in Android and IOS. This is the Code:
render(){
let pulse = <Image source={require('../pulse.png')} style={styles.pulse} />
return (
<SafeAreaView style={styles.container}>
<View>
<StatusBar barStyle="dark-content" />
<View style={{ flex: 0.4, resizeMode: 'contain' }}>
<Text style={styles.appName}>L{pulse}blood</Text>
</View>
</View>
</SafeAreaView>
}
These are the styles
container: {
flex: 1,
backgroundColor: 'white',
},
appName: {
alignSelf: 'center',
fontFamily: 'oswald',
fontSize: 50,
color: 'black',
height: '100%'
}
You need to remove the flex prop of the child view. Change
<View style={{ flex: 0.4, resizeMode: 'contain' }}>
<Text style={styles.appName}>L{pulse}blood</Text>
</View>
to
<View style={{ resizeMode: 'contain' }}>
<Text style={styles.appName}>L{pulse}blood</Text>
</View>
I'm trying to have a list and then a button, but if I try to have a button and then a list like so:
return (
<View style={styles.mainContainer}>
<View>
<TouchableOpacity style={styles.Button} onPress={() => this.props.navigate(1)}>
{buttonText}
</TouchableOpacity>
</View>
<ScrollView>
<View style={{ height: 250, backgroundColor: 'red' }}>
</View>
<View style={{ height: 250, backgroundColor: 'blue' }}>
</View>
<View style={{ height: 250, backgroundColor: 'green' }}>
</View>
</ScrollView>
</View>
);
You see that green isn't being fully shown:
This doesn't happen if the button isn't there.
And if I move
<View>
<TouchableOpacity style={styles.Button} onPress={() => this.props.navigate(1)}>
{buttonText}
</TouchableOpacity>
</View>
to be after the ScrollView, I don't see the button.
So to sum it up, I want the button to be stickied to the bottom while having every element in the scroll view to be fully shown. How can it be done?
This is the style of the button BTW:
Button: {
borderWidth: 1,
borderRadius: 10,
padding: 10,
marginTop: 5,
margin: 3,
backgroundColor: '#4267b2',
borderColor: '#ffffff',
alignItems: 'center'
}
he proper way to achieve this is by using flex
this is an example for 1 : 10 flex body to header ratio
render() {
return (
<View style={styles.mainContainer}>
<View style={styles.bodyContainer}>
<ScrollView >
<View style={{ height: 250, backgroundColor: 'red' }}>
</View>
<View style={{ height: 250, backgroundColor: 'blue' }}>
</View>
<View style={{ height: 250, backgroundColor: 'green' }}>
</View>
</ScrollView>
</View>
<View style={styles.headerContainer}>
<Button style={{ backgroundColor: 'blue', alignSelf:'center' }}
title="THIS IS A BUTTON" />
</View>
</View>
);
}
}
const styles = StyleSheet.create({
mainContainer: {
flex: 1,
flexDirection: 'column'
},
headerContainer: {
flex: 1,
},
bodyContainer: {
flex: 10
}
});
You can stick your button view with a position: absolute, set its height and add a margin-bottom of this height on the scrollview.
Render
return (
<View style={styles.mainContainer}>
<ScrollView style={styles.list}>
<View style={{ height: 250, backgroundColor: 'red' }}>
</View>
<View style={{ height: 250, backgroundColor: 'blue' }}>
</View>
<View style={{ height: 250, backgroundColor: 'green' }}>
</View>
</ScrollView>
<View style={styles.fixedBottom}>
<TouchableOpacity style={styles.Button} onPress={() => this.props.navigate(1)}>
{buttonText}
</TouchableOpacity>
</View>
</View>
);
Style
...
fixedBottom: {
position: 'absolute',
left: 0,
right: 0,
bottom: 0,
height: 50, // <== the height on your view containing the button
backgroundColor: 'gray',
},
list: {
alignSelf: 'stretch',
flex: 1,
marginBottom: 50, // <== here the margin to see the full list
},
...
Here is a live demo.
I'm trying to a implement a logic to display some data fetched from a simple REST API. So i'm grabbing the JSON object in the RanjoorExplore class and the data is sent into the data to the ExploreCard in the other class. So the this.props.data must be referencing the passed variable. By mapping that variable, I'm displaying the title attribute of the response object in a simple Text Component.
I'm facing this error:
undefined is not a function(evaluating this.props.data.map).
RanjoorExplore:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image,
ScrollView,
Alert
} from 'react-native';
import Icon from 'react-native-vector-icons/FontAwesome';
import ExploreCard from '../../elements/cards/ExploreCard';
import ExploreHeader from '../../elements/headers/ExploreHeader';
class RanjoorExplore extends Component {
constructor(){
super();
this.state = {
rawData: []
}
}
static navigationOptions = {
header: null,
title: 'Explore',
tabBarIcon: ({ tintColor, focused }) => (
<Icon
name="bandcamp"
size={24}
color={focused ? '#4ab367' : 'white'}
/>
),
headerStyle: { backgroundColor: '#202026' },
headerTitleStyle: {
color: 'white'
}
};
fetchGanjoorData() {
return fetch('https://jsonplaceholder.typicode.com/posts/1')
.then((response) => response.json())
.then((responseJson) => {
this.setState({rawData: responseJson})
})
.catch((error) => {
console.error(error);
});
}
componentDidMount() {
this.fetchGanjoorData();
}
render() {
return (
<View style={styles.ExploreContainer}>
<ExploreHeader />
<ScrollView>
<ExploreCard data={this.state.rawData} />
</ScrollView>
</View>
);
}
}
var styles = StyleSheet.create({
ExploreContainer: {
backgroundColor: '#303036',
height: '100%',
width: '100%'
},
})
export default RanjoorExplore
ExploreCard:
import React, { Component } from 'react';
import {
StyleSheet,
Text,
View,
Image,
Alert
} from 'react-native';
import { Card, ListItem, Button, Icon, Avatar } from 'react-native-elements';
export default class ExploreCard extends Component {
render() {
/* Mapped data will be processed right here */
let mappedData = this.props.data.map(function (data1) {
return (
<View>
{data1.title}
</View>
)
})
return (
<View style={{ flexDirection: 'row' }}>
<View style={{ flex: 1 }}></View>
<Card
containerStyle={{
width: '85%', height: 250, backgroundColor: '#202026', shadowOpacity: 0.7,
shadowOffset: { height: 5 }, shadowColor: 'black', borderWidth: 0, borderRadius: 8, flexDirection: 'row'
}}
wrapperStyle={{ alignSelf: 'flex-end' }} >
<View style={{ flex: 2, alignSelf: 'flex-end' }}>
<View style={{ flexDirection: 'row', alignSelf: 'flex-end' }}>
<Text style={{ fontFamily: 'IRANSans', marginRight: 5, marginTop: 12, color: '#505056' }}>حافظ</Text>
<Avatar
medium
rounded
source={require('../../img/avatars/ferdowsi.jpg')}
containerStyle={{
alignSelf: 'flex-end', marginRight: 15,
shadowOpacity: 0.7,
shadowOffset: { height: 5 }, shadowColor: 'black'
}}
/>
</View>
<View>
<Text style={{ alignSelf: 'flex-end', fontFamily: 'IRANSans', color: 'white', marginTop: '10%', marginRight: '5%' }}>
{mappedData}
</Text>
<Text style={{ alignSelf: 'flex-start', fontFamily: 'IRANSans', color: 'white' }}>
تا دمی برآساییم زین حجاب ظلمانی
</Text>
</View>
</View>
<View style={{ alignSelf: 'flex-end', backgroundColor: 'transparent', flexDirection: 'row' }}>
<Icon
name='favorite' size={24} color="#34343a" style={{ marginLeft: 5 }}
/>
<Icon
name='grade' size={24} color="#34343a" style={{ marginLeft: 5 }}
/>
<View>
<Button
textStyle={{ fontSize: 15 }}
iconRight
backgroundColor='#4ab367'
fontFamily='IRANSans_UltraLight'
buttonStyle={{
height: 15, width: 110,
borderRadius: 8
}}
title='ادامه مطلب'
/>
</View>
</View>
</Card>
<View style={{ flex: 1 }}></View>
</View>
);
}
}
Can someone please help me solve this issue?
Thanks in advance.
https://jsonplaceholder.typicode.com/posts/1 returns an object, not an array. Therefore, map is not a valid operation
Perhaps you meant to use https://jsonplaceholder.typicode.com/posts/? That returns an array
I have recently started using React-Native, and one of the main issues I have been struggling with is the layout design.
I have a "Card" like component that holds some information about movies. Components like Image and Text that are big goes out of the bounds of the card and does not respect the padding and margins provided.
Here is the JSX code:
<View style={[styles.container, styles.card]}>
<View style={{alignSelf: 'stretch', flexDirection: 'row', padding: 10}}>
<Image style={{height: 50, width: 50, borderRadius: 25}}
source={require('../../img/sarah-avatar.png.jpeg')}/>
<View style={{flexDirection: 'column', marginTop: 5, marginLeft: 15}}>
<Text style={styles.title}>{ this.state.movie.name }</Text>
<Text style={{color: 'gray'}}>{ moment(this.state.movie.releaseDate).format('DD/MM/YYYY') }</Text>
</View>
</View>
<View style={{alignItems: 'center'}}>
<!-- THIS IMAGE DOES NOT RESPECT THE CARD BOUNDS -->
<Image style={{height: 220, resizeMode: 'center'}}
source={require('../../img/advance-card-bttf.png')}/>
<View style={{flexWrap: 'wrap', marginTop: 10, marginBottom: 20}}>
<Text style={{color: 'gray', fontSize: 14}}>
{ this.state.movie.summary }
</Text>
</View>
</View>
<View style={{flexDirection: 'row', flex: 1}}>
<Button onPress={this.onLikeClick.bind(this)}>
<View style={{flexDirection: 'row'}}>
<Icon name="thumbs-up" size={18} color="#007aff" />
<Text style={{color: '#007aff', marginLeft: 5}}>{ this.state.movie.likes } Likes</Text>
</View>
</Button>
<View style={{width: 20}} />
<Button onPress={this.onCommentClick.bind(this)}>
<View style={{flexDirection: 'row'}}>
<Icon name="comment" size={18} color="#007aff" />
<Text style={{color: '#007aff', marginLeft: 5}}>{ this.state.movie.comments.length } Comments</Text>
</View>
</Button>
</View>
<Comments comments={this.state.movie.comments }
showComments={ this.state.showComments }
handler={this.handler} />
</View>
const styles = StyleSheet.create({
card: {
backgroundColor: "#fff",
borderRadius: 2,
shadowColor: "#000000",
shadowOpacity: 0.3,
shadowRadius: 1,
shadowOffset: {
height: 1,
width: 0.3,
},
padding: 10,
flexWrap: 'wrap'
},
container: {
flex: 1,
backgroundColor: '#F5FCFF',
margin: 5
},
title: {
fontSize: 20,
backgroundColor: 'transparent'
},
button: {
marginRight: 10
}
});
And the comments component JSX code:
<View style={{flexDirection: 'column'}}>
{
this.props.comments.map((comment, index) => {
return (
<View key={index} style={{flexDirection: 'row', marginTop: 20}}>
<Image style={{height: 50, width: 50, borderRadius: 25}}
source={require('../../img/avatar-ts-woody.png')}/>
<View style={{flexDirection: 'column', marginLeft: 15, marginTop: 3}}>
<Text style={{fontSize: 18}}>{ comment.name }</Text>
<!-- THE COMMENT CONTENT GOES OUTSIDE OF THE CARD -->
<Text style={{color: 'gray'}}>{ comment.content }</Text>
</View>
</View>
)
})
}
<TextInput placeholder="Leave a comment"
value={this.state.commentContent}
onChangeText={(text) => this.setState({commentContent : text})}
onSubmitEditing={this.onCommentEntered.bind(this)}
style={{height: 40, marginTop: 18}} />
</View>
Here you can see that the cover image seems like it's out of the card:
In here each comment might start correctly inside the card, but will go outside of the bounds when text is too long:
I am using react-native .My input field is not display on full width why ? But when I check on IOS it works correctly display input field on full width .
here is my code
https://rnplay.org/apps/aHRkHA
import React from 'react';
import {
registerComponent,
} from 'react-native-playground';
import {
StatusBar,
StyleSheet,
Text,
TextInput,
View,
} from 'react-native';
class App extends React.Component {
render() {
return (
<View style={styles.container}>
<Text style={styles.heading}> Login</Text>
<TextInput
style={styles.loginInput}
placeholder="Type here to translate!"
/>
</View>
);
}
}
const styles = StyleSheet.create({
container: {
backgroundColor: '#EF501E',
flex: 1,
alignItems: 'center'
},
logo: {
width: 50,
height: 50
},
heading: {
fontSize: 30,
marginTop: 20
},
loginInput: {
height: 50,
borderWidth: 1,
borderColor: '#33090C',
flexDirection: 'row',
justifyContent: 'center',
}
});
registerComponent(App);
Try overriding the alignItems: 'center' of the parent with alignSelf: 'stretch' for <TextInput>:
<View style={styles.container}>
...
<View style={{alignSelf: 'stretch'}}>
<TextInput
style={styles.loginInput}
placeholder="Type here to translate!"
/>
</View>
</View>