設定畫面Navigation

使用 react-navigation (v1)

https://v1.reactnavigation.org/docs/tab-based-navigation.html

  1. 前往 src/navigatior.js

設置TabBar中每個TabBar的名稱

 {
    Home: { screen: Home },
    Counter: { screen: Counter },
    Camera: { screen: Camera },
    PersonalInfo: { screen: PersonalInfo, navigationOptions: { title: '個人資訊' } },
    MerchandiseList: { screen: MerchandiseList, navigationOptions: { title: '我的商品' } },
    NewMerchandise: { screen: NewMerchandise, navigationOptions: { title: '建立商品' } },
    MerchandiseGrid: { screen: MerchandiseGrid, navigationOptions: { title: '商城' } },
    MerchandiseDetail: { screen: MerchandiseDetail, navigationOptions: { title: '商品詳細' } }
  },

設置TabBar的Icon

對TabNavigator 設置Icon 使用 react-native-vector-icons/FontAwesome

與設置選中(active)與沒選中(inactive)的顏色

 {
    navigationOptions: ({ navigation }) => ({
      tabBarIcon: ({ focused, tintColor }) => {
        const { routeName } = navigation.state;

        const ICON_MAP = {
          PersonalInfo: 'user',
          MerchandiseList: 'archive',
          NewMerchandise: 'plus',
          MerchandiseGrid: 'th',
          MerchandiseDetail: 'info-circle'
        };
        // You can return any component that you like here! We usually use an
        // icon component from react-native-vector-icons
        return <Icon name={ICON_MAP[routeName] || ''} size={24} color={tintColor} />;
      }
    }),
    tabBarOptions: {
      activeTintColor: 'tomato',
      inactiveTintColor: 'gray'
    },
    tabBarComponent: TabBarBottom,
    tabBarPosition: 'bottom',
    animationEnabled: false,
    swipeEnabled: false
  }

調整TabBar 的高度與Tab中 每個TabBar的文字大小

tabBarOptions 中 加入style

const styles = StyleSheet.create({
  tabBar: {
    height: 90
  },
  tabLabel: {
    fontSize: 16
  }
});

...     
tabBarOptions: {
    activeTintColor: 'tomato',
    inactiveTintColor: 'gray',
    style: styles.tabBar,
    labelStyle: styles.tabLabel
},

將某些畫面不在TabNavigator 中出現

例如相機這是由某個頁面的動作去開啟的行為,不應該在TabBar中出現,使用StackNavigator 包住原本的AppNavigator,並把那些需要全螢幕的畫面放置在StackNavigator中

const RootNavigator = new StackNavigator(
  {
    App: { screen: AppNavigator },
    Home: { screen: Home },
    Counter: { screen: Counter },
    Camera: { screen: Camera }
  },
  {
    headerMode: 'none'
  }
);

還有部分畫面是屬於某個頁面開啟,但它還是需要TabBar在下面進行操作,因為那些畫面屬於商城的一部分,譬如說個人頁面->上傳商品->商品管理這樣的操作路徑,這時候我們可以在某個Tab頁面的screen放置StackNavigator 來做到此事

 {
    PersonalInfo: {
      screen: new StackNavigator({
        PersonalInfo: { screen: PersonalInfo, navigationOptions: { title: '商品清單' } },
        MerchandiseList: { screen: MerchandiseList, navigationOptions: { title: '我的商品' } },
        NewMerchandise: { screen: NewMerchandise, navigationOptions: { title: '建立商品' } }
      }),
      navigationOptions: { title: '個人資訊' }
    },
    MerchandiseGrid: { screen: MerchandiseGrid, navigationOptions: { title: '商城' } },
    MerchandiseDetail: {
      screen: MerchandiseDetail,
      navigationOptions: { title: '商品詳細', tabBarVisible: false }
    }
  },

新增BadgeIcon

  • 可以自由發揮layout 的技巧,以下是參考範例

  • numberOfBadges做為傳入參數,代表有幾則通知

  • 以setParams 的方式來傳遞numberOfBadges

      const styles = StyleSheet.create({
        ....
        badge: {
          position: 'absolute',
          right: -20,
          top: -10,
          borderRadius: 15,
          width: 30,
          height: 30,
          backgroundColor: '#e12',
          color: 'white',
          textAlign: 'center',
          fontSize: 20
        }
      });
    
      const BadgeIcon = (props) => {
        const { numberOfBadges } = props;
        const show = !!numberOfBadges;
        return (
          <View>
            <Icon {...props} />
            {show && <Text style={styles.badge}> {`${numberOfBadges}`}</Text>}
          </View>
        );
      };

    更新其他頁面的通知數量

    • 透過setParams

      • 但只能更新自己,因為每個頁面都有屬於自己的route params

        • 因為react-navigation 有跟redux store 做結合,將想更新的值打到store 內,用key指定要更新的store name e.g. TransactionRecord

        • 在navigationOptions 中來接收

  • const setParamsAction = NavigationActions.setParams({
        params: { numberOfBadges: result },
        key: 'TransactionRecord'
      });
    this.props.navigation.dispatch(setParamsAction);
navigationOptions: ({ navigation }) => ({
    tabBarIcon: ({ tintColor }) => {
      const { routeName } = navigation.state;

      const ICON_MAP = {
        PersonalInfo: 'user',
        MerchandiseList: 'archive',
        NewMerchandise: 'plus',
        MerchandiseGrid: 'th',
        MerchandiseDetail: 'info-circle',
        TransactionRecord: 'list',
        ShoppingCart: 'shopping-cart'
      };
      // You can return any component that you like here! We usually use an
      // icon component from react-native-vector-icons
      const routeParams = navigation.state.params || {};

      return (
        <BadgeIcon
          name={ICON_MAP[routeName] || ''}
          size={42}
          color={tintColor}
          numberOfBadges={routeParams.numberOfBadges}
        />
      );
    }
})

部分頁面關掉TabBar顯示或是部分頁面打開 StackNavigator's Header

headerMode - Specifies how the header should be rendered:

    float - Render a single header that stays at the top and animates as screens are changed. This is a common pattern on iOS.
    screen - Each screen has a header attached to it and the header fades in and out together with the screen. This is a common pattern on Android.
const AppNavigator = new TabNavigator(
  {
    MerchandiseGrid: new StackNavigator(
      {
        MerchandiseGrid: {
          screen: MerchandiseGrid,
          navigationOptions: { title: '商城', header: null } // disable header but open all headers in here
        },
        MerchandiseDetail: {
          screen: MerchandiseDetail,
          navigationOptions: { title: '商品詳細', tabBarVisible: false }
        }
      },
      {
        headerMode: 'screen'
      }
    ),
  }

參考資料:

https://github.com/react-navigation/react-navigation/issues/293#issuecomment-279146748

https://github.com/react-navigation/react-navigation/issues/608

Why console.log slow

https://github.com/evgenyrodionov/redux-logger/issues/32

Last updated