Reactjs StackNavigator中的嵌套TabNavigator:控制标题
我有一个类似这样的设置:Reactjs StackNavigator中的嵌套TabNavigator:控制标题,reactjs,react-native,react-navigation,Reactjs,React Native,React Navigation,我有一个类似这样的设置: let Tabs = createBottomTabNavigator({ screen1: Screen1, screen2: Screen2 }) let Stack = createStackNavigator({ tabs: Tabs otherScreen: OtherScreen }) 堆栈导航器有一个标题,这很好。我想要的是根据我当前所在的选项卡获得不同的标题图标 我正在使用以下版本: "react": "16.3.1"
let Tabs = createBottomTabNavigator({
screen1: Screen1,
screen2: Screen2
})
let Stack = createStackNavigator({
tabs: Tabs
otherScreen: OtherScreen
})
堆栈导航器有一个标题,这很好。我想要的是根据我当前所在的选项卡获得不同的标题图标
我正在使用以下版本:
"react": "16.3.1",
"react-native": "~0.55.2",
"react-navigation": "^2.2.5"
我已经考虑过切换我的设置,这样每个选项卡屏幕都有自己的
StackNavigator
,但是我喜欢在切换选项卡时有滑动动画,我不希望标题图标滑动。标题栏应保持静态,但仅根据当前选项卡显示不同的图标。您可以使用当前导航堆栈配置实现所需的行为。你可能需要改变一些东西,并结合一些属性,但当你开始考虑它时,这是相当简单的
我试着用一个小例子来解释它
考虑使用下面的导航器
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
})
如您所见,我正在从导航状态设置title参数。要想为导航器设置参数,我们需要从属性获取帮助
class TabsPage extends Component {
onTabsChange = (title) => {
this.props.navigation.setParams({ title })
}
render() {
return(<Tabs screenProps={{ onTabsChange: this.onTabsChange }} />)
}
}
当我们聚焦选项卡时,传递的函数将运行,然后为该选项卡设置标题。您可以使用此过程为标题设置不同的按钮或图标。您可以找到工作零食。您可以像下面这样使用 //(navigation.state.routes[navigation.state.index])[“routeName”] //(navigation.state.routes[navigation.state.index][“routes”])[(navigation.state.routes[navigation.state.index][“index”])]
this will give the current route name of the tab inside StackNavigation.
上面的代码将TabBar所在的根堆栈头中的标题设置为第一个路由,因此我们将TabBar中单个堆栈的头设置为null。通过使用这种方式,将在切换选项卡栏中的屏幕时提供动画,因为标题将保持静态
你可以在这里找到工作副本
下载此文件并执行以下操作
在AppNavigation.js//中,或您已定义路线的位置
let Tabs=createBottomTabNavigator({
屏幕1:屏幕1,
屏幕2:屏幕2
})
让Stack=createStackNavigator({
标签:标签
其他屏幕:其他屏幕
},{
headerMode:“float”//渲染一个停留在顶部的标题,并在屏幕更改时设置动画。这是iOS上的常见模式。
headerTransitionPreset:“淡入位”//当标题图标更改时,这将提供轻微的过渡。
}
)
const RootStack=createStackNavigator(
{
主屏幕:{屏幕:主屏幕},
过滤器屏幕:CreateMaterialOptabNavigator({
Tab1:{screen:Tab1Screen},
Tab2:{screen:Tab2Screen},
}),
},
{
模式:“模态”,
headerMode:“无”,
}
);
render(){
返回;
}
如果您使用的是react导航,您只需使用属性headershow:false
。我创建了一个react导航
版本的工作示例:5.x.x
,嵌套了不同的导航器:堆栈
,抽屉
&底部选项卡
以下是github的链接:
有关更详细的概述,您可以查看我的博客:
这确实是一个更好的解决方案,但如何导航到“其他屏幕”?this.props.navigation.navigate('Page');在Tab1或TAB2中不起作用,您可以检查此问题吗@bennygenel@AnthonyDe Smet,我已经更新了我的答案,请检查一下,让我知道这是否解决了您的问题。虽然这是可行的,但您不能将标题更改为routeName以外的任何内容,可以吗?e、 g.“Screen2”标题将始终为“Screen2”,或者您是否可以将其设置为:“子项XXX的屏幕标题”?@Chris,我已根据您的要求更新了我的答案。您可以通过在navigationOptions中使用与routeName匹配的switch case来设置标题headerLeft,headerRight等。通过这种方式,我们可以设置标题,而不必考虑routeName。@dhivyas我还有一个关于嵌套选项卡的问题,你认为我们可以用类似的解决方案来解决吗?你能检查这个Q@dhivyas你能检查这个Q@Ashwinmothillalcan你能检查这个Q@Rajatgupta你能检查这个Q@MahdiBashirpour吗
//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: ({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 }
}
}
{
"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"
}
this will give the current route name of the tab inside StackNavigation.
const RootStack = createStackNavigator(
{
Home: {screen: HomeScreen},
FilterScreen: createMaterialTopTabNavigator({
Tab1: {screen:Tab1Screen},
Tab2: {screen: Tab2Screen},
}),
},
{
mode: 'modal',
headerMode: 'none',
}
);
render() {
return <RootStack/>;
}
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
})
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
}
}