簡體   English   中英

React Native - 帶屏幕的移動標簽欄

[英]React Native - Move Tab Bar with Screens

我的靈感來自 Up Bank 中的選項卡導航,您可以在此處看到這篇文章的一半左右。

目前我正在使用React Native Material Top Tab Navigator ,它有一個 position 屬性,可以從 Navigator 組件傳遞到位於屏幕上方的 Tab Bar 中。 因此,我認為對這個位置道具使用插值是讓它發揮作用的最佳方式。

我還在此處找到了這篇文章,我發現它是推動事物發展的非常有用的資源。 盡管如此,我還是不能完全讓屏幕與導航選項卡齊平,尤其是在您添加/刪除頁面時。

我對React Native Gesture Handler有一個想法,但是 Tab Navigator 似乎是建立在這個基礎上的,並且還使用 useLayoutEffect 和其他掛鈎來獲取選項卡元素的位置並在更改時更新它。 目前我覺得插值是要走的路,但很高興被證明是錯誤的(如果我被證明是錯誤的工作解決方案更好)。

我當前的代碼:

const Tab = createMaterialTopTabNavigator();

const { width } = Dimensions.get("screen");

export const TabNavBar = ({
  state,
  navigation,
  position,
}: MaterialTopTabBarProps): JSX.Element => {
  const [tabPostion, setTabPosition] = React.useState(0);

  const routes = state.routes.length;

  const tabDifference = width / routes;

  const inputRange = [
    state.index - routes,
    state.index,
    state.index,
    state.index + routes,
  ];

  const translateXPosition = position.interpolate({
    inputRange,
    outputRange: [tabDifference, -37.5, -37.5, -tabDifference],
  });

  React.useEffect(() => {
    setTabPosition(translateXPosition);
  }, []);

  return (
    <View
      style={{
        paddingTop: 50,
        flexDirection: "row",
        height: 100,
        backgroundColor: "white",
      }}
    >
      <Animated.View
        style={{
          flex: 1,
          flexDirection: "row",
          alignItems: "center",
          transform: [{ translateX: tabPostion }],
          position: "absolute",
          left: "25%",
          top: 50,
        }}
      >
        {state.routes.map((route, index) => {
          const label = route.name;

          return (
            <TouchableOpacity
              key={index}
              style={{ position: "relative", paddingHorizontal: 20 }}
            >
              <Animated.Text>{label}</Animated.Text>
            </TouchableOpacity>
          );
        })}
      </Animated.View>
    </View>
  );
};

function TabNavigator() {
  return (
    <Tab.Navigator
      initialRouteName="TabTwo"
      tabBar={(props) => <TabNavBar {...props} />}
    >
      <Tab.Screen name="TabOne" component={TabOneScreen} />
      <Tab.Screen name="TabTwo" component={TabTwoScreen} />
      <Tab.Screen name="TabThree" component={TabThreeScreen} />
      <Tab.Screen name="TabFour" component={TabFourScreen} />
      <Tab.Screen name="TabFive" component={TabFiveScreen} />
    </Tab.Navigator>
  );
}

神速啦。 任何幫助是極大的贊賞!

用非任意數字替換-37.5應該可以解決您的問題。 除非你有任何死區,否則你應該能夠將你的輸入設置為從0到你擁有的屏幕數。

對於輸出值,您可以使用希望屏幕出現在第一頁上的位置,最大值是標簽欄出現在最終屏幕上的位置。

一個例子看起來像這樣:

const Tab = createMaterialTopTabNavigator();

const { width } = Dimensions.get("screen");

export const TabNavBar = ({
  state,
  navigation,
  position,
}: MaterialTopTabBarProps): JSX.Element => {
  const [tabPostion, setTabPosition] = React.useState(0);

  const routes = state.routes.length;

  const tabDifference = width / routes;

  const inputRange = [
    0, // First Screen
    routes // Final Screen
  ];

  const translateXPosition = position.interpolate({
    inputRange,
    outputRange: [tabDifference, tabDifference * routes],
  });

  React.useEffect(() => {
    setTabPosition(translateXPosition);
  }, []);

  return (
    <View
      style={{
        paddingTop: 50,
        flexDirection: "row",
        height: 100,
        backgroundColor: "white",
      }}
    >
      <Animated.View
        style={{
          flex: 1,
          flexDirection: "row",
          alignItems: "center",
          transform: [{ translateX: tabPostion }],
          position: "absolute",
          left: "25%",
          top: 50,
        }}
      >
        {state.routes.map((route, index) => {
          const label = route.name;

          return (
            <TouchableOpacity
              key={index}
              style={{ position: "relative", paddingHorizontal: 20 }}
            >
              <Animated.Text>{label}</Animated.Text>
            </TouchableOpacity>
          );
        })}
      </Animated.View>
    </View>
  );
};

function TabNavigator() {
  return (
    <Tab.Navigator
      initialRouteName="TabTwo"
      tabBar={(props) => <TabNavBar {...props} />}
    >
      <Tab.Screen name="TabOne" component={TabOneScreen} />
      <Tab.Screen name="TabTwo" component={TabTwoScreen} />
      <Tab.Screen name="TabThree" component={TabThreeScreen} />
      <Tab.Screen name="TabFour" component={TabFourScreen} />
      <Tab.Screen name="TabFive" component={TabFiveScreen} />
    </Tab.Navigator>
  );
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM