it-swarm.com.de

Verschachtelter TabNavigator in StackNavigator: Steuerung der Kopfzeile

Ich habe ein sehr ähnliches Setup:

let Tabs = createBottomTabNavigator({
    screen1: Screen1,
    screen2: Screen2
})

let Stack = createStackNavigator({
    tabs: Tabs
    otherScreen: OtherScreen
})

Der Stack-Navigator hat einen Header, und das ist in Ordnung. Was ich möchte, ist, unterschiedliche Kopfzeilensymbole zu erhalten, abhängig davon, auf welcher Registerkarte ich gerade bin.

Ich verwende folgende Versionen:

"react": "16.3.1",
"react-native": "~0.55.2",
"react-navigation": "^2.2.5"

Ich habe mir überlegt, mein Setup so zu ändern, dass jeder Tab-Bildschirm seine eigene StackNavigator hat, aber ich mag die gleitende Animation beim Wechseln der Tabs und ich möchte nicht, dass die Kopfzeilen-Icons mitrutschen. Die Kopfleiste sollte statisch bleiben, aber abhängig von der aktuellen Registerkarte einfach andere Symbole anzeigen.

6
Anthony De Smet

Sie können wie folgt verwenden: https://reactnavigation.org/docs/de/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"-) //(navigation.state.routes[navigation.state.index(["routes"-))[(nnavigation.state.routes[navigation.state.index( 

this will give the current route name of the tab inside StackNavigation.

Der obige Code setzt den Titel im Root-Stack-Header, in dem sich die TabBar befindet, als erste Route. Daher setzen wir den Header als Null für den einzelnen Stack in TabBar. Auf diese Weise werden Animationen bereitgestellt, während Sie die Bildschirme in der TabBar wechseln, da der Header statisch bleibt.

die Arbeitskopie finden Sie hier https://www.dropbox.com/s/jca6ssn9zkzh9kn/Archive.zip?dl=0

Laden Sie dieses herunter und führen Sie Folgendes aus.

  1. npm install // um Abhängigkeiten zu erhalten 

  2. reaktives Upgrade // für Android- und iOS-Ordner

  3. reaktiver Link // zur Verknüpfung von Abhängigkeiten und Bibliotheken

  4. reaktives Run-Ios (oder) Reaktives Run-Android

    sie können die oben genannten verwenden, lassen Sie es mich wissen.

6
dhivya s

Sie können das gewünschte Verhalten mit der aktuellen Konfiguration Ihres Navigationsstapels erreichen. Möglicherweise müssen Sie einige Dinge ändern und einige Eigenschaften kombinieren, aber es ist ziemlich einfach, wenn Sie sich damit auseinandersetzen.

Ich versuche es mit einem kleinen Beispiel zu erklären.

Betrachten Sie unter Navigatoren;

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
})

Wie Sie sehen, stelle ich den Titelparameter aus dem Navigationsstatus ein. Um den Parameter für diesen Navigator festzulegen, erhalten Sie Hilfe von screenProps property;

class TabsPage extends Component {
  onTabsChange = (title) => {
    this.props.navigation.setParams({ title })
  }
  render() {
    return(<Tabs screenProps={{ onTabsChange: this.onTabsChange }} />)
  }
}

Ich habe eine Wrapper-Komponente für den Tab-Navigator erstellt und eine Funktion übergeben, die den Titelparameter setzt.

Für den letzten Teil müssen wir wissen, wie und wann wir diese Funktion verwenden sollten, die wir weitergegeben haben. Dafür verwenden wir 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>
  }
}

Wenn unser Tab fokussiert ist, wird die übergebene Funktion ausgeführt und der Titel für diesen Tab festgelegt. Sie können diesen Prozess verwenden, um verschiedene Schaltflächen oder Symbole für die Kopfzeile festzulegen. Den Arbeitssnack finden Sie hier .

2
bennygenel

In AppNavigation.js // oder wo Sie Ihre Routen definiert haben.

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.
  }
)

In Screen1.js

class Screen1 extends Component {
 
 static navigationOptions = ({ navigation }) => {

    return {
      ...
      headerLeft: <HeaderLeftImage navigation={navigation} image={"Image_For_Screen1"}/>,
      ...
    }
  }
  ...
}

HINWEIS: Sie können Titel, HeaderStil, HeaderRight auf dieselbe Weise hinzufügen. Lesen Sie diesen Link Header-Konfiguration , um weitere Informationen zu erhalten

In Screen2.js ähnlich wie 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>
)

Hoffe, das hilft, wenn Sie Zweifel bezüglich des Codes haben, fragen Sie einfach.

0
Rajat Gupta

Wenn Sie reagieren, navigieren Sie <2, dh ~ 1,5. * Sie können es so einstellen.

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
})

Ich bin nicht sicher, warum sie diese Funktion entfernt haben. Wenn Sie dasselbe versuchen, funktioniert sie nicht mit der neuesten reag-navigation. Nun wird der Titelobjektschlüssel für den Fallback verwendet.

Dies kann bei einigen Benutzern hilfreich sein. Wenn Sie möchten, können Sie auch ein Downgrade durchführen. 

Ich habe die React Navigation für mein Projekt aktualisiert. Ich denke, dieser Weg wird für jemanden nützlich sein

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
}
}
0
Ashwin Mothilal
const RootStack = createStackNavigator(
  {
    Home: {screen: HomeScreen},
    FilterScreen: createMaterialTopTabNavigator({
        Tab1: {screen:Tab1Screen},
        Tab2: {screen: Tab2Screen},
    }),
  },
  {
    mode: 'modal',
    headerMode: 'none',
  }
);


render() {
    return <RootStack/>;
}
0