J'ai une configuration un peu comme ceci:
let Tabs = createBottomTabNavigator({
screen1: Screen1,
screen2: Screen2
})
let Stack = createStackNavigator({
tabs: Tabs
otherScreen: OtherScreen
})
Le navigateur de pile a un en-tête, et c'est bien. Ce que je veux, c'est obtenir différentes icônes d'en-tête en fonction de l'onglet sur lequel je suis actuellement.
J'utilise les versions suivantes:
"react": "16.3.1",
"react-native": "~0.55.2",
"react-navigation": "^2.2.5"
J'ai envisagé de changer ma configuration pour que chaque écran d'onglets ait sa propre StackNavigator
, mais j'aime bien avoir l'animation glissante lorsque je change d'onglet et je ne veux pas que les icônes d'en-tête glissent. La barre d'en-tête doit rester statique mais afficher simplement des icônes différentes en fonction de l'onglet en cours.
Vous pouvez utiliser comme ceci ci-dessous, https://reactnavigation.org/docs/fr/stack-navigator.html
//Screen1 Stack.
const Screen1 = createStackNavigator ({
Home: {
screen: Home,
navigationOptions: {
header: null //Need to set header as null.
}
}
});
//Screen2 Stack
const Screen2 = createStackNavigator ({
Profile: {
screen: Profile,
navigationOptions: {
header: null //Need to set header as null.
}
}
});
let Tabs = createMaterialTopTabNavigator({
Screen1:{
screen: Screen1 //Calling Screen1 Stack.
},
Screen2:{
screen: Screen2 //Calling Screen2 Stack.
}
},{ tabBarPosition: 'bottom' }) //this will set the TabBar at Bottom of your screen.
let Stack = createStackNavigator({
tabs:{
screen: Tabs, //You can add the NavigationOption here with navigation as parameter using destructuring.
navigationOptions: ({navigation})=>{
//title: (navigation.state.routes[navigation.state.index])["routeName"]
//this will fetch the routeName of Tabs in TabNavigation. If you set the routename of the TabNavigation as your Header.
//use the following title property,this will fetch the current stack's routeName which will be set as your header in the TabBar.
//title: (navigation.state.routes[navigation.state.index]["routes"])[(navigation.state.routes[navigation.state.index]["index"])].routeName
//you can use switch case,on matching the route name you can set title of the header that you want and also header left and right icons similarly.
switch ((navigation.state.routes[navigation.state.index]["routes"])[(navigation.state.routes[navigation.state.index]["index"])].routeName) {
case "Screen1":
return {
title: "Home",
headerLeft: (<Button
onPress={()=> alert("hi")}
title="Back"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/> ),
headerRight: <Button title= "Right"/>
}
case "Screen2":
return {
title: "Profile",
headerLeft: (<Button
onPress={()=> alert("hi")}
title="Back"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/> ),
headerRight: <Button title= "Right"/>
}
default:
return { title: (navigation.state.routes[navigation.state.index]["routes"])[(navigation.state.routes[navigation.state.index]["index"])].routeName }
}
}
},
otherScreen:{
screen: OtherScreen
}
})
// navigationOptions
navigationOptions: ({navigation})=>{
//title: (navigation.state.routes[navigation.state.index])["routeName"]
//this will fetch the routeName of Tabs in TabNavigation. If you set the routename of the TabNavigation as your Header.
//use the following title property,this will fetch the current stack's routeName which will be set as your header in the TabBar.
//title: (navigation.state.routes[navigation.state.index]["routes"])[(navigation.state.routes[navigation.state.index]["index"])].routeName
switch ((navigation.state.routes[navigation.state.index]["routes"])[(navigation.state.routes[navigation.state.index]["index"])].routeName) {
case "Screen1":
return {
title: "Home",
headerLeft: (<Button
onPress={()=> alert("hi")} //Here you can able to set the back behaviour.
title="Back"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/> ),
headerRight: <Button title= "Right"/>
}
case "Screen2":
return {
title: "Profile",
headerLeft: (<Button
onPress={()=> alert("hi")}
title="Back"
color="#841584"
accessibilityLabel="Learn more about this purple button"
/> ),
headerRight: <Button title= "Right"/>
}
default:
return { title: (navigation.state.routes[navigation.state.index]["routes"])[(navigation.state.routes[navigation.state.index]["index"])].routeName }
}
}
//alert(navigation.state)
{
"routes":[
{
"key":"Screen1",
"routeName":"Screen1",
"routes":[
{
"key":"Home",
"routeName":"Home",
}
],
"index":0,
"isTransitioning":false,
"key":"id-1530276062643-0"
},
{
"key":"Screen2",
"routeName":"Screen2",
"routes":[
{
"key":"Profile",
"routeName":"Profile",
}
],
"index":0,
"isTransitioning":false,
"key":"id-1530276062643-0"
}
],
"index":0,
"isTransitioning":false,
"routeName":"tabs",
"key":"id-1530276062643-0"
}
//(navigation.state.routes[navigation.state.index])["routeName"aser //(navigation.state.routes Suivre
this will give the current route name of the tab inside StackNavigation.
Le code ci-dessus définira le titre dans l'en-tête de la pile racine où le TabBar réside en tant que première route. Nous définissons donc l'en-tête comme null pour la pile individuelle dans TabBar. En utilisant cette méthode, vous obtiendrez une animation tout en commutant les écrans dans TabBar puisque l’en-tête restera statique.
vous pouvez trouver la copie de travail ici https://www.dropbox.com/s/jca6ssn9zkzh9kn/Archive.zip?dl=0
Téléchargez ceci et exécutez ce qui suit.
npm install // pour obtenir des dépendances
réactif-mise à niveau native // pour obtenir le dossier Android et ios
react-native link // pour lier des dépendances et des bibliothèques
réactif natif run-ios (ou) réactif natif run-Android
vous pouvez utiliser ce qui précède, laissez-moi savoir si.
Vous pouvez obtenir le comportement souhaité avec la configuration actuelle de la pile de navigation. Vous aurez peut-être besoin de changer plusieurs choses et de combiner plusieurs propriétés, mais c'est assez simple quand vous comprenez mieux.
J'essaie de l'expliquer avec un petit exemple.
Pensez à avoir ci-dessous des navigateurs;
const Tabs = createBottomTabNavigator({
screen1: Tab1,
screen2: Tab2
})
const Stack = createStackNavigator({
tabs: {
screen: TabsPage,
navigationOptions: ({navigation}) => {
return { title: (navigation.state.params && navigation.state.params.title ? navigation.state.params.title : 'No Title' ) }
}
},
otherScreen: Page
})
Comme vous pouvez le constater, je configure le paramètre title à partir de l'état de navigation. Pour pouvoir définir les paramètres de ce navigateur, nous allons obtenir de l'aide de screenProps
property;
class TabsPage extends Component {
onTabsChange = (title) => {
this.props.navigation.setParams({ title })
}
render() {
return(<Tabs screenProps={{ onTabsChange: this.onTabsChange }} />)
}
}
J'ai créé un composant wrapper pour le navigateur de tabulation et transmis une fonction qui définit le paramètre title.
Pour la dernière partie, nous devons savoir comment et quand utiliser cette fonction que nous avons transmise. Pour cela, nous allons utiliser addListener
navigation prop
class Tab1 extends React.Component {
setTitle = () => {
this.props.screenProps.onTabsChange('Title from Tab 1')
}
componentDidMount() {
this.props.navigation.addListener('willFocus', this.setTitle)
}
render() {
return <View><Text>{'Tab1'}</Text></View>
}
}
Lorsque notre onglet est activé, la fonction transmise s’exécute puis définit le titre de cet onglet. Vous pouvez utiliser cette procédure pour définir différents boutons ou icônes pour l'en-tête. Vous pouvez trouver la collation de travail ici .
Dans AppNavigation.js // ou si vous avez défini vos itinéraires.
let Tabs = createBottomTabNavigator({
screen1: Screen1,
screen2: Screen2
})
let Stack = createStackNavigator({
tabs: Tabs
otherScreen: OtherScreen
},{
headerMode:"float", //Render a single header that stays at the top and animates as screens are changed. This is a common pattern on iOS.
headerTransitionPreset:"fade-in-place" //this will give a slight transition when header icon change.
}
)
Dans Screen1.js
class Screen1 extends Component {
static navigationOptions = ({ navigation }) => {
return {
...
headerLeft: <HeaderLeftImage navigation={navigation} image={"Image_For_Screen1"}/>,
...
}
}
...
}
NOTE: Vous pouvez ajouter title, headersStyle, headerRight de la même manière, lisez ce lien en-tête de configuration pour plus de détails.
Dans Screen2.js faire similaire à Screen1
class Screen2 extends Component {
static navigationOptions = ({ navigation }) => {
return {
...
headerLeft: <HeaderLeftImage navigation={navigation} image={"Image_For_Screen2"}/>,
...
}
}
...
}
Header.js
export const HeaderLeftImage = (props) => (
<View style={{
'add styles'
}}>
<TouchableOpacity onPress={() => {"Add action here" }}>
<Image source={props.image} resizeMethod='resize' style={{ height: 30, width: 90, resizeMode: 'contain' }} />
</TouchableOpacity>
</View>
)
J'espère que cela vous aidera, si vous avez des doutes sur le code, n'hésitez pas à demander.
Si vous utilisez la navigation réactive <2, c'est-à-dire ~ 1,5. * Vous pouvez le définir comme ceci.
const Tabs = TabNavigator({
Tab1:{
screen: Tab1,
navigationOptions: ({navigation}) => {
return { title: "Tab 1 Heading", tabBarLabel:"Tab 1 "}
},
}
Tab2:{
screen: Tab2
navigationOptions: ({navigation}) => {
return { title: "Tab 2 Heading", tabBarLabel:"Tab 2 "}
}
}
})
const Stack = StackNavigator({
tabs: {
screen: Tabs
navigationOptions: ({navigation}) => {
return { title: "Stack"}
}
},
otherScreen: Page
})
Je ne suis pas sûr de savoir pourquoi ils ont supprimé cette fonctionnalité. Lorsque vous essayez la même chose, cela ne fonctionnera pas avec la dernière version de réaction-navigation Maintenant, la clé d'objet de titre est utilisée pour le repli semble-t-il.
Cela peut être utile à certains utilisateurs. Si vous le souhaitez, vous pouvez également essayer de déclasser.
J'ai mis à niveau la navigation React pour mon projet, je pense que cette façon sera utile à quelqu'un
const Tabs = TabNavigator({
Tab1:{
screen: Tab1,
navigationOptions: ({navigation}) => {
return { tabBarLabel:"Tab 1 "}
}},
Tab2:{
screen: Tab2
navigationOptions: ({navigation}) => {
return { tabBarLabel:"Tab 2 "}
}}
});
Tabs.navigationOptions = ({navigation})=>{
const { routeName } = navigation.state.routes[navigation.state.index]; //This gives current route
switch(routeName){
case "Tab1":
headerTitle="Tab 1";
break;
case "Tab1":
headerTitle="Tab 1";
break;
}
return {
headerTitle: headerTitle
}
}
const RootStack = createStackNavigator(
{
Home: {screen: HomeScreen},
FilterScreen: createMaterialTopTabNavigator({
Tab1: {screen:Tab1Screen},
Tab2: {screen: Tab2Screen},
}),
},
{
mode: 'modal',
headerMode: 'none',
}
);
render() {
return <RootStack/>;
}