0

我正在尝试使用 fromtabBarComponent为我的 React Native 应用程序使用自定义组件(属性)createMaterialTopTabNavigator"react-native-tabs"该组件是BottomNavigationfrom "react-native-paper"

我已经从https://github.com/react-navigation/material-bottom-tabs复制了几乎所有的代码,因为它是我找到的BottomNavigation用作自定义组件的唯一来源

我有 3 段主要代码: TabNavigator (component)

class CustomTabNavigator extends React.Component {
_getColor = ({ route }) => {
  const { descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const options = descriptor.options;

  if (this.context === 'dark' && options.tabBarColorDark) {
    return options.tabBarColorDark;
  } else if (options.tabBarColorLight) {
    return options.tabBarColorLight;
  } else {
    return options.tabBarColor;
  }
};

_getactiveColor = () => {
  let { activeColor, activeColorLight, activeColorDark } = this.props;

  if (this.context === 'dark' && activeColorDark) {
    return activeColorDark;
  } else if (activeColorLight) {
    return activeColorLight;
  } else {
    return activeColor;
  }
};

_getInactiveColor = () => {
  let { inactiveColor, inactiveColorLight, inactiveColorDark } = this.props;

  if (this.context === 'dark' && inactiveColorDark) {
    return inactiveColorDark;
  } else if (inactiveColorLight) {
    return inactiveColorLight;
  } else {
    return inactiveColor;
  }
};

_getBarStyle = () => {
  let { barStyle, barStyleLight, barStyleDark } = this.props;

  return [barStyle, this.context === 'dark' ? barStyleDark : barStyleLight];
};

_isVisible() {
  const { navigation, descriptors } = this.props;
  const { state } = navigation;
  const route = state.routes[state.index];
  const options = descriptors[route.key].options;
  return options.tabBarVisible;
}

_renderIcon = ({
  route,
  focused,
  color,
}) => {
  return this.props.renderIcon({ route, focused, tintColor: color });
};

render() {
  const {
    navigation,
    descriptors,
    ...rest
  } = this.props;

  const activeColor = this._getactiveColor();
  const inactiveColor = this._getInactiveColor();
  const barStyle = this._getBarStyle();

  const isVisible = this._isVisible();
  const extraStyle =
    isVisible === false
      ? {
          display: 'none',
          position: undefined,
        }
      : null;

  return (
    <BottomNavigation
      {...rest}
      activeColor={activeColor}
      inactiveColor={inactiveColor}
      renderIcon={this._renderIcon}
      barStyle={[barStyle, extraStyle]}
      navigationState={navigation.state}
      getColor={this._getColor}
    />
  )
}
}

TabNavigation (navigator)

class CustomTabNavigation extends React.Component {
_renderScene = ({ route }) => {
  const { screenProps, descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const TabComponent = descriptor.getComponent();
  return (
    <SceneView
      screenProps={screenProps}
      navigation={descriptor.navigation}
      component={TabComponent}
    />
  );
};

_renderIcon = ({
  route,
  focused,
  tintColor,
  horizontal = false,
}) => {
  const { descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const options = descriptor.options;

  if (options.tabBarIcon) {
    return typeof options.tabBarIcon === 'function'
      ? options.tabBarIcon({ focused, tintColor, horizontal })
      : options.tabBarIcon;
  }

  return null;
};

_getLabelText = ({ route }) => {
  const { descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const options = descriptor.options;

  if (options.tabBarLabel) {
    return options.tabBarLabel;
  }

  if (typeof options.title === 'string') {
    return options.title;
  }

  return route.routeName;
};

_getAccessibilityLabel = ({ route }) => {
  const { descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const options = descriptor.options;

  if (typeof options.tabBarAccessibilityLabel !== 'undefined') {
    return options.tabBarAccessibilityLabel;
  }

  const label = this._getLabelText({ route });

  if (typeof label === 'string') {
    const { routes } = this.props.navigation.state;
    return `${label}, tab, ${routes.indexOf(route) + 1} of ${
      routes.length
    }`;
  }

  return undefined;
};

_getTestID = ({ route }) => {
  const { descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const options = descriptor.options;

  return options.tabBarTestID;
};

_getBadge = ({ route }) => {
  const { descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const options = descriptor.options;

  return options.tabBarBadge;
};

_makeDefaultHandler = ({
  route,
  navigation,
}) => () => {
  if (navigation.isFocused()) {
    if (route.hasOwnProperty('index') && route.index > 0) {
      navigation.dispatch(StackActions.popToTop({ key: route.key }));
    } else {
      navigation.emit('refocus');
    }
  } else {
    this._jumpTo(route.routeName);
  }
};

_handleTabPress = ({ route }) => {
  this._isTabPress = true;
  Promise.resolve().then(() => (this._isTabPress = false));

  const { descriptors } = this.props;
  const descriptor = descriptors[route.key];
  const { navigation, options } = descriptor;

  const defaultHandler = this._makeDefaultHandler({ route, navigation });

  if (options.tabBarOnPress) {
    options.tabBarOnPress({ navigation, defaultHandler });
  } else {
    defaultHandler();
  }
};

_handleIndexChange = index => {
  if (this._isTabPress) {
    this._isTabPress = false;
    return;
  }

  this._jumpTo(this.props.navigation.state.routes[index].routeName);
};

_jumpTo = routeName => {
  const { navigation } = this.props;

  navigation.dispatch(
    SwitchActions.jumpTo({
      routeName,
      key: navigation.state.key,
    })
  );
};

_isTabPress = false;

render() {
  const {
    descriptors,
    navigation,
    screenProps,
    navigationConfig,
  } = this.props;
  const { state } = navigation;
  const route = state.routes[state.index];
  const descriptor = descriptors[route.key];
  const options = {
    ...navigationConfig,
    ...descriptor.options,
  };

  return (
    <CustomTabNavigator
      {...options}
      getLabelText={this._getLabelText}
      getAccessibilityLabel={this._getAccessibilityLabel}
      getTestID={this._getTestID}
      getBadge={this._getBadge}
      renderIcon={this._renderIcon}
      renderScene={this._renderScene}
      onIndexChange={this._handleIndexChange}
      onTabPress={this._handleTabPress}
      navigation={navigation}
      descriptors={descriptors}
      screenProps={screenProps}
    />
  );
}
}

Main navigation

const TabNavigator = createStackNavigator(
{
  TabsStack: {
    ...,
    {
      ...,
      tabBarComponent: ({ props }) => <CustomTabNavigation {...props} />
    })
  },
}
);

我希望能够从“react-navigation”中使用该swipeEnabled功能(与每个屏幕之间的动画转换)createMaterialTopTabNavigator,以及具有更好看的标签栏,但它在(line )'navigation.state is undefined'的渲染功能中表示,但我看不出原因。CustomTabNavigationconst { state } = navigation;

4

1 回答 1

0

我认为这里有错误:tabBarComponent: ({ props }) => <CustomTabNavigation {...props} />应该是tabBarComponent : props => <CustomTabNavigation {...props} />或只是tabBarComponent: CustomTabNavigation

BottomNavigationfrom paper 不是标签栏组件,它是一个完整的标签导航组件。我猜你可以通过不渲染内容来像标签栏一样使用它。

但考虑到 Android 和 iOS 设计指南都没有向底部标签添加滑动手势,因此 UX 会不一致。通常顶部标签栏有滑动手势,因为用手指更难到达顶部栏。

于 2019-11-01T03:46:50.373 回答