javascript - Comment changer de vues sur le même écran (React Native) ?
Je veux dupliquer ce qui suit avec react-native-scrollable-tab-view :
Actuellement, mon code est le suivant, mais je ne sais pas comment exécuter et incorporer le module pour faciliter les choses - quelqu'un a-t-il des idées sur la façon dont je peux mettre cela en œuvre ? (Je suis novice donc toute aide est appréciée) :
Ceci est l'onglet principal (vue par onglets) :
'use strict';
var React = require('react-native');
var Dimensions = require('Dimensions');
var window = Dimensions.get('window');
var Icon = require('react-native-vector-icons/FontAwesome');
var Restaurants = require('../Helpers/Restaurants');
var More = require('../Helpers/More');
var api = require('../Api/Api');
var Profile = require('../Helpers/Profile');
var Recipes = require('../Helpers/Recipes');
var Actions = require('react-native-router-flux').Actions;
var Home = require('../Helpers/Home');
var {
StyleSheet,
Text,
View,
Image,
TabBarIOS,
Component
} = React;
class Main extends React.Component{
constructor(props) {
super(props);
this.state = {
selectedTab: 'home',
notifCount: 0,
presses: 0,
};
}
GoBack() {
this.props.navigator.pop();
}
render() {
return (
<TabBarIOS
tintColor="#49B64D"
barTintColor="rgba(255,255,255,0.3)"
selectedTab={this.state.selectedTab}>
<Icon.TabBarItem
selected={this.state.selectedTab === 'home'}
icon={require('image!homeicon')}
onPress={() => {
this.setState({
selectedTab: 'home',
});
}}>
<Home/>
</Icon.TabBarItem>
<Icon.TabBarItem
selected={this.state.selectedTab === 'restaurants'}
icon={require('image!nomicon')}
onPress={() => {
this.setState({
selectedTab: 'restaurants',
});
}}>
<Restaurants/>
</Icon.TabBarItem>
<Icon.TabBarItem
selected={this.state.selectedTab === 'recipes'}
icon={require('image!haticon')}
onPress={() => {
this.setState({
selectedTab: 'recipes',
});
}}>
<Recipes/>
</Icon.TabBarItem>
<Icon.TabBarItem
selected={this.state.selectedTab === 'profile'}
icon={require('image!accounticon')}
onPress={() => {
this.setState({
selectedTab: 'profile',
});
}}>
<Profile/>
</Icon.TabBarItem>
</TabBarIOS>
);
}
};
var styles = StyleSheet.create({
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'transparent'
},
bgImage: {
flex: 1,
width: window.width,
resizeMode: 'cover',
},
});
module.exports = Main;
Voici la vue des recettes lorsque vous cliquez sur l'onglet des recettes :
'use strict';
var React = require('react-native');
var Seperator = require('./Seperator');
var api = require('../Api/Api');
var Dimensions = require('Dimensions');
var window = Dimensions.get('window');
var LinearGradient = require('react-native-linear-gradient');
var Swipeout = require('react-native-swipeout');
var List = require('./List');
var RecipeDetails = require('./RecipeDetails');
var Actions = require('react-native-router-flux').Actions;
var {
ScrollView,
Text,
View,
TouchableHighlight,
StyleSheet,
Image,
ListView,
NavigatorIOS,
} = React;
var styles = StyleSheet.create({
description: {
fontSize: 20,
textAlign: 'center',
color: '#FFFFFF'
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'transparent',
},
linearGradient: {
flex: 1,
paddingLeft: 15,
paddingRight: 15,
borderRadius: 5,
opacity: 0.9,
height: window.width,
},
dietText: {
color:'white',
fontFamily: 'Avenir Next',
alignSelf:'center',
},
title: {
textAlign:'left',
marginTop: (window.width/1.4),
fontSize: 20,
color: 'white',
fontFamily: 'Avenir Next',
fontWeight: '500',
},
dietbuble: {
backgroundColor:'transparent',
height:20,
width:60,
borderRadius: 10,
backgroundColor:'#49B64D',
marginRight:5,
},
nombtn: {
height: 30,
width: 30,
marginBottom: 5,
},
arrow: {
height: 15,
width: 15,
marginRight: 20,
marginTop: 5,
},
upvotenum: {
marginRight: 5,
fontSize: 20,
fontWeight: "600",
color: 'white',
fontFamily: 'Avenir Next'
},
dish_num: {
backgroundColor:'#49B64D',
height: 30,
width: 100,
marginLeft: window.width/1.36,
borderRadius: 5,
},
dishtext: {
fontFamily: "Avenir Next",
fontSize: 20,
fontWeight: "400",
textAlign: 'center',
color:"white",
},
profilebubble: {
width: 40,
height: 40,
borderRadius: 20,
margin: 2,
}
});
var list = [
{
component: <List/>
}
]
class Recipes extends React.Component{
constructor(props) {
super(props);
this.state = {
venues: new Object(),
};
}
activateHome() {
api.getAnything(this.props.paleo,this.props.vegan,this.props.vegetarian,this.props.healthy,this.props.dairyfree,this.props.nutfree,this.props.glutenfree)
.then((res) => {
console.log(res);
return res;
});
}
detailsRecipe() {
this.props.navigator.push ({
component: RecipeDetails,
title: "",
})
}
render(){
return (
<ScrollView
alwaysBounceVertical={true}
scrollEventThrottle={200}>
<Swipeout right={list}>
<View style={styles.container}>
<Image source={{uri: 'http://i.huffpost.com/gadgets/slideshows/404432/slide_404432_5031844_free.jpg'}} style={{width: window.width, height: window.width}}>
<View style={{backgroundColor: 'transparent', marginBottom: 100,}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<Image source={{uri: 'http://cookieandkate.com/images/2014/02/kate-600.jpg'}} style={styles.profilebubble}/>
<Image source={{uri: 'http://www.thetimes.co.uk/tto/multimedia/archive/00851/82ef9ae8-ae34-11e4-_851122b.jpg'}} style={styles.profilebubble}/>
</View>
</View>
<LinearGradient colors={['transparent', 'transparent', '#1C1C1C']} style={styles.linearGradient}>
<TouchableHighlight onPress={Actions.recipedetails} underlayColor='transparent'>
<View style={{backgroundColor:'transparent', height: window.width, marginTop:-20}}>
<Text style={styles.title}>Recipe Name | 10 Mins</Text>
</View>
</TouchableHighlight>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent', marginTop: -75}}>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegan</Text>
</View>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegie</Text>
</View>
<View style={{flex: 1, flexDirection: 'row', marginLeft: window.width/3, backgroundColor: 'transparent'}}>
<Text style={styles.upvotenum} >20</Text>
<Image style={styles.arrow} source={require('image!upvotearrow')}></Image>
<Image style={styles.nombtn} source={require('image!nombtn')}></Image>
</View>
</View>
</LinearGradient>
</View>
</Image>
</View>
</Swipeout>
<Seperator/>
<Swipeout right={list}>
<View style={styles.container}>
<Image source={{uri: 'http://www.funkinutt.com/wp-content/uploads/2013/06/Vegan-Scallops-Sophies-Kitchen.jpg'}} style={{width: window.width, height: window.width}}>
<View style={{backgroundColor: 'transparent', marginBottom: 100,}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<Image source={{uri: 'http://cookieandkate.com/images/2014/02/kate-600.jpg'}} style={styles.profilebubble}/>
<Image source={{uri: 'http://www.thetimes.co.uk/tto/multimedia/archive/00851/82ef9ae8-ae34-11e4-_851122b.jpg'}} style={styles.profilebubble}/>
</View>
</View>
<LinearGradient colors={['transparent', 'transparent', '#1C1C1C']} style={styles.linearGradient}>
<TouchableHighlight onPress={Actions.recipedetails} underlayColor='transparent'>
<View style={{backgroundColor:'transparent', height: window.width, marginTop:-20}}>
<Text style={styles.title}>Recipe Name | 10 Mins</Text>
</View>
</TouchableHighlight>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent', marginTop: -75}}>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegan</Text>
</View>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegie</Text>
</View>
<View style={{flex: 1, flexDirection: 'row', marginLeft: window.width/3, backgroundColor: 'transparent'}}>
<Text style={styles.upvotenum} >20</Text>
<Image style={styles.arrow} source={require('image!upvotearrow')}></Image>
<Image style={styles.nombtn} source={require('image!nombtn')}></Image>
</View>
</View>
</LinearGradient>
</View>
</Image>
</View>
</Swipeout>
<Seperator/>
<Swipeout right={list}>
<View style={styles.container}>
<Image source={{uri: 'http://m5.paperblog.com/i/37/370315/guest-blogger-vegan-richa-samosa-and-onion-bh-L-KmHfF4.jpeg'}} style={{width: window.width, height: window.width}}>
<View style={{backgroundColor: 'transparent', marginBottom: 100,}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<Image source={{uri: 'http://cookieandkate.com/images/2014/02/kate-600.jpg'}} style={styles.profilebubble}/>
<Image source={{uri: 'http://www.thetimes.co.uk/tto/multimedia/archive/00851/82ef9ae8-ae34-11e4-_851122b.jpg'}} style={styles.profilebubble}/>
</View>
</View>
<LinearGradient colors={['transparent', 'transparent', '#1C1C1C']} style={styles.linearGradient}>
<TouchableHighlight onPress={Actions.recipedetails} underlayColor='transparent'>
<View style={{backgroundColor:'transparent', height: window.width, marginTop:-20}}>
<Text style={styles.title}>Recipe Name | 10 Mins</Text>
</View>
</TouchableHighlight>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent', marginTop: -75}}>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegan</Text>
</View>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegie</Text>
</View>
<View style={{flex: 1, flexDirection: 'row', marginLeft: window.width/3, backgroundColor: 'transparent'}}>
<Text style={styles.upvotenum} >20</Text>
<Image style={styles.arrow} source={require('image!upvotearrow')}></Image>
<Image style={styles.nombtn} source={require('image!nombtn')}></Image>
</View>
</View>
</LinearGradient>
</View>
</Image>
</View>
</Swipeout>
<Seperator/>
<Swipeout right={list}>
<View style={styles.container}>
<Image source={{uri: 'http://www.choosingraw.com/wp-content/uploads/2014/09/IMG_8328.jpg'}} style={{width: window.width, height: window.width}}>
<View style={{backgroundColor: 'transparent', marginBottom: 100,}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<Image source={{uri: 'http://cookieandkate.com/images/2014/02/kate-600.jpg'}} style={styles.profilebubble}/>
<Image source={{uri: 'http://www.thetimes.co.uk/tto/multimedia/archive/00851/82ef9ae8-ae34-11e4-_851122b.jpg'}} style={styles.profilebubble}/>
</View>
</View>
<LinearGradient colors={['transparent', 'transparent', '#1C1C1C']} style={styles.linearGradient}>
<TouchableHighlight onPress={Actions.recipedetails} underlayColor='transparent'>
<View style={{backgroundColor:'transparent', height: window.width, marginTop:-20}}>
<Text style={styles.title}>Recipe Name | 10 Mins</Text>
</View>
</TouchableHighlight>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent', marginTop: -75}}>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegan</Text>
</View>
<View style={styles.dietbuble}>
<Text style={styles.dietText}>Vegie</Text>
</View>
<View style={{flex: 1, flexDirection: 'row', marginLeft: window.width/3, backgroundColor: 'transparent'}}>
<Text style={styles.upvotenum} >20</Text>
<Image style={styles.arrow} source={require('image!upvotearrow')}></Image>
<Image style={styles.nombtn} source={require('image!nombtn')}></Image>
</View>
</View>
</LinearGradient>
</View>
</Image>
</View>
</Swipeout>
<Seperator/>
</ScrollView>
)
}
};
module.exports = Recipes;
Et voici la vue des détails de la recette :
'use strict';
var React = require('react-native');
var Dimensions = require('Dimensions');
var window = Dimensions.get('window');
var LinearGradient = require('react-native-linear-gradient');
var Tabbar = require('react-native-tabbar');
var Item = Tabbar.Item;
var {
StyleSheet,
View,
Text,
Component,
Image,
ScrollView,
TouchableHighlight,
} = React;
var styles = StyleSheet.create({
description: {
fontSize: 20,
textAlign: 'center',
color: '#FFFFFF'
},
container: {
flex: 1,
justifyContent: 'center',
alignItems: 'center',
backgroundColor: 'transparent',
},
venue_image: {
width: window.width,
height: window.height/4,
flex: 1,
},
linearGradient: {
flex: 1,
paddingLeft: 15,
paddingRight: 15,
opacity: 0.9,
height: window.height/3.7,
},
title: {
textAlign:'left',
fontSize: 15,
color: 'white',
fontFamily: 'Avenir Next',
fontWeight: '500',
},
nombtn: {
height: 30,
width: 30,
marginBottom: 5,
},
arrow: {
height: 15,
width: 15,
marginRight: 20,
marginTop: 5,
},
upvotenum: {
marginRight: 5,
fontSize: 20,
fontWeight: "600",
color: 'white',
fontFamily: 'Avenir Next'
},
dietbuble: {
backgroundColor:'transparent',
height:20,
width:60,
borderRadius: 10,
backgroundColor:'#49B64D',
marginRight:5,
},
submenutext: {
fontFamily: 'Avenir Next',
fontSize: 15,
fontWeight: '600',
color: 'white',
alignSelf: 'center',
marginTop: 10,
},
undernum: {
fontFamily: 'Avenir Next',
fontSize: 30,
fontWeight: '400',
color: 'white',
alignSelf: 'center',
},
units: {
fontFamily: 'Avenir Next',
fontSize: 10,
color: 'white',
alignSelf: 'center',
}
});
class VenueDetails extends React.Component {
constructor(props) {
super(props);
this.state = {
selectedTab: 'ingredients',
};
}
_Directions() {
this.setState({selectedTab: 'directions'});
console.log(this.state.selectedTab);
}
_Nutrition() {
this.setState({selectedTab: 'nutrition'});
console.log(this.state.selectedTab);
}
_Ingredients() {
this.setState({selectedTab: 'ingredients'});
console.log(this.state.selectedTab);
}
makeBackground(btn){
var featurebox = {
flex: 1,
height: window.width/4,
width: window.width/3,
alignItems: 'center',
justifyContent: 'center',
}
if(btn === 0 || btn === 2){
featurebox.backgroundColor = '#49B64D';
} else if (btn === 1){
featurebox.backgroundColor = '#585858';
}
return featurebox;
}
render() {
return (
<View style={styles.container}>
<View style={styles.container}>
<Image source={{uri: 'http://i.huffpost.com/gadgets/slideshows/404432/slide_404432_5031844_free.jpg'}} style={styles.venue_image}>
<LinearGradient colors={['transparent', 'transparent', '#1C1C1C']} style={styles.linearGradient}>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent', marginTop: window.height/4.3}}>
<View style={{backgroundColor:'transparent', marginRight: window.width/4, marginLeft: 10}}>
<Text style={styles.title}>Recipe Name | 10 Mins</Text>
</View>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<Text style={styles.upvotenum} >20</Text>
<Image style={styles.arrow} source={require('image!upvotearrow')}></Image>
<Image style={styles.nombtn} source={require('image!nombtn')}></Image>
</View>
</View>
</LinearGradient>
</Image>
</View>
<View style={{flex: 1, flexDirection: 'row', backgroundColor: 'transparent'}}>
<TouchableHighlight
onPress={this._Ingredients.bind(this)}
style={this.makeBackground(0)}
underlayColor='transparent'>
<View>
<Text style={styles.submenutext}>Ingredients</Text>
<Text style={styles.undernum}>5</Text>
<Text style={styles.units}>Count</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
onPress={this._Nutrition.bind(this)}
style={this.makeBackground(1)}
underlayColor='transparent'>
<View>
<Text style={styles.submenutext}>Nutrition</Text>
<Text style={styles.undernum}>200</Text>
<Text style={styles.units}>Sugars</Text>
</View>
</TouchableHighlight>
<TouchableHighlight
onPress={this._Directions.bind(this)}
style={this.makeBackground(2)}
underlayColor='transparent'>
<View>
<Text style={styles.submenutext}>Directions</Text>
<Text style={styles.undernum}>10</Text>
<Text style={styles.units}>Hours</Text>
</View>
</TouchableHighlight>
</View>
<ScrollView>
</ScrollView>
</View>
);
}
}
module.exports = VenueDetails;
Actuellement, tout cela ressemble à ceci :
Réponse #1
Ce que je ferais, c'est créer un tableau d'objets avec chaque objet représentant les différentes vues/composants dans votre curseur de pied de page. Ensuite, avoir une propriété dans votre état qui est l'onglet actif et quand un utilisateur clique sur un nouvel onglet, mettre à jour l'onglet actif avec l'index correspondant au nouvel onglet. Ce que nous allons faire, c'est, quel que soit l'onglet actif, prendre ce composant spécifique que vous avez dans le tabMap que vous avez créé ci-dessus et le rendre. Le code ressemblera à quelque chose comme ça.
var tabMap = [
{key: 0, icon: 'ion|ios-contact-outline', state: 'bio', asArray: false, Component: About},
{key: 1, icon: 'ion|ios-paper', state: 'posts', asArray: true, Component: Posts},
{key: 2, icon: 'ion|ios-people', state: 'friends', asArray: false, Component: Friends},
{key: 3, icon: 'ion|ios-heart', state: 'activity', asArray: false, Component: Activity},
];
Donc cela représente différentes onglets dans la section inférieure.
getInitialState(){
return {
activeTab: 0
}
}
C'est mon état initial qui va garder la trace de l'onglet sur lequel je me trouve.
Puis dans ma méthode de rendu, je récupère le composant de l’onglet actif actuel,
var BodyComponent = tabMap[this.state.activeTabIndex].Component;
Maintenant que j'ai le composant, je peux simplement rendre BodyComponent en passant les données que je souhaite.
<BodyComponent
header={tabMap[this.state.activeTabIndex].header}
authedUser={this.props.authedUser}
isGuest={this.props.isGuest}
userToRender={this.state.userToRender}
data={this.state[tabMap[this.state.activeTabIndex].state]} />
Réponse #2
C'était une fonctionnalité manquante de react-native-router-flux (pour passer d'un 'onglet' à l'autre dans un même conteneur) et je l'ai ajoutée récemment, veuillez vérifier la dernière version.
Vous devez utiliser l'élément Container et définir vos routes à l'intérieur. Vous devez également définir l'implémentation de TabBar à utiliser avec ce conteneur (consultez l'exemple avec son TabBarFlux)

