react-navigation2.0版之Tab导航

2018-06-30  本文已影响0人  既然可以颠覆何必循规蹈矩

本文章的版本是react-navigation 2.5.5
一般来说构建app有两种思路:
方法1:如果我的App 有几个 tab 就需要用 createStackNavigator建立几个stack,然后用一个createBottomTabNavigator包裹刚刚创建的几个stack。类似于ios原生
方法2:反过来用stack包裹一个tab和好多screen(单独的页面)
下面分别说说这两种构建:

C4451C7A-7D11-4B8F-B68E-31EC851FBB7E.png
//首页     详情页
const HomeStack = createStackNavigator({
  Home: HomeScreen,
  Details: DetailsScreen,
});

//我的 我的设置
const MeStack = createStackNavigator({
  Me: MeScreen,
  Setting: SettingScreen,
  // Details: DetailsScreen 跨tab跳转需要额外注册
});

然后通过 createBottomTabNavigator把stack包裹

export default createBottomTabNavigator(
{
  Home: HomeStack,
  Me: MeStack,
});

这种写法有个缺点就是子页面也会存在下面的tab 而且需要在每个stack 判断一下。2.0的处理方法如下:

HomeStack.navigationOptions = ({ navigation }) => {
  let tabBarVisible = true;
  if (navigation.state.index > 0) {
    tabBarVisible = false;
  }
  return {
    tabBarVisible,
  };
};

如果需要夸tab跳转就额外注册,比如我要从Me 里面跳转到 Details 则需要在 MeStack 里面 设置 Details: DetailsScreen

或者你采用另外一个布局方式 stack包裹tab

const TabOptions = (tabBarTitle, tabBarIconName) => {
    const title = tabBarTitle;
    const tabBarIcon = (({tintColor,focused})=> {
        const color = focused ? CS.THEME11 : CS.COLOR4;
        if(title){
            return(
                <Icon name={tabBarIconName} size={title?FS.ICON_B:40} color={color}/>
            )
        }else {
            return(
                <FontAwesome name={tabBarIconName} size={44} color={CS.THEME11}/>
            )
        }

    });
    const tabBarVisible = true;
    return { title, tabBarIcon, tabBarVisible };
};

const MyTab = createBottomTabNavigator({
    ScreenHome: {
        screen: ScreenHome,
        navigationOptions: ()=> TabOptions('找房', 'oneIcon|icon_search'),
    },

    ScreenGroup: {
        screen: ScreenGroup,
        navigationOptions: ()=> TabOptions('圈子', 'oneIcon|icon_fenxiaoquan_light'),
    },

    ScreenAdd: { screen: ScreenAdd,
        // 这里我实现了隐藏单个文字的tab  达到了类似微博的效果我是修改了源码
        navigationOptions: ()=> TabOptions('','plus-circle'),
    },

    ScreenMessage: {
        screen: ScreenMessage,
        navigationOptions: ()=> TabOptions('消息', 'oneIcon|icon__xiaoxi'),
    },

    ScreenMe: {
        screen: ScreenMe,
        navigationOptions: ()=> TabOptions('我的', 'oneIcon|icon_me'),
    },
})
const AppStack = createStackNavigator({
        MyTab : MyTab,
        Detail : Detail
})

但是这种方法也有一个问题 就是tab页面的头不好隐藏,1.0版本的方式不适用了,需要做如下处理

MyTab.navigationOptions = ({ navigation }) => {
    let { routeName } = navigation.state.routes[navigation.state.index];
    if(routeName=='ScreenHome'||routeName=='ScreenGroup'||routeName=='ScreenMe'){
        return {
            header:null,
        };
    }else if(routeName=='ScreenAdd'){
        return {
            headerTitle:'发布',
        };
    }else if(routeName=='ScreenMessage'){
        return {
            headerTitle:'消息',
        };
    }
};

需要隐藏单个文字的话修改源码如下:
自己额外加了一个判断,文件路径 node_modules/react-navigation-tabs/dist/views 30多行左右

if (typeof label === 'string') {
      if(label==''){
          return null;
      }else {
          return <Animated.Text numberOfLines={1} style={[styles.label, { color: tintColor }, showIcon && this._shouldUseHorizontalLabels() ? styles.labelBeside : styles.labelBeneath, styles.labelBeneath, labelStyle]} allowFontScaling={allowFontScaling}>
              {label}
          </Animated.Text>;
      }
    }

那么我们的登录流程和怎么和tab结合呢

这个时候我们就要用到createSwitchNavigator.说白了createSwitchNavigator里面的只能显示一个,这个就相当于之前的reset()方法.不处理回退操作,切换时将路由重置为默认状态. 他跳转(navigate())后其余的页面都销毁了

// 这里演示的是第二种方式
const AppStack = createStackNavigator({
       MyTab : MyTab,
       Detail : Detail
})
const LoginStack = createStackNavigator({
   Login : Login,
   Register : Register,
});

export defaul const AppNavigator = createSwitchNavigator({
   Splash : Splash,  // 这是引导页
   LoginStack : LoginStack,  // 这里包含登录前的所有页面,比如注册,登录 ,忘记密码 等
   App : AppStack, // 这里面包含所有登录后的页面
});

上一篇下一篇

猜你喜欢

热点阅读