You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

TopTabBar滚动动画引发页面黑条,需实现滚动时TabBar上移且页面完整

滚动时TabBar动画导致页面底部黑条修复方案

问题

实现向上滚动时TopTabBar(含Logo)向上隐藏的动画,向下滚动时显示,但执行后整个页面上移,底部出现黑条,需消除黑条并保证页面完整显示,且无法调整TopReelTabNavigator的屏幕尺寸。

问题根源

原代码将包含Logo和TabNavigator的整个容器设置了translateY动画,导致所有页面内容跟随容器上移,底部空出动画偏移量对应的高度,从而出现黑条;同时子页面固定设置height={window.height + 60},进一步加剧了内容错位。

解决方案

1. 重构TopReelTabNavigator:单独动画顶部栏(Logo+TabBar)

将Logo和TabBar作为独立的可动画容器,页面内容区域保持原位,通过动态调整内容的paddingTop适配顶部栏的显示/隐藏状态。

修改后的TopReelTabNavigator代码:

const TopReelTab = createMaterialTopTabNavigator<ReelStackParamList>();

export function TopReelTabNavigator() {
  const [scrollDirection, setScrollDirection] = useState("null");
  // 计算Logo+TabBar总高度(Logo45px + 默认TabBar高度56px)
  const TOP_BAR_TOTAL_HEIGHT = 45 + 56;
  const topBarTranslateY = useState(new Animated.Value(0))[0];

  useEffect(() => {
    if (scrollDirection === "bas") {
      // 向上滚动时,顶部栏完全隐藏
      Animated.timing(topBarTranslateY, {
        toValue: -TOP_BAR_TOTAL_HEIGHT,
        duration: 300,
        useNativeDriver: true,
      }).start();
    } else {
      // 向下滚动或滚动到顶部时,顶部栏还原
      Animated.timing(topBarTranslateY, {
        toValue: 0,
        duration: 300,
        useNativeDriver: true,
      }).start();
    }
  }, [scrollDirection]);

  return (
    <SafeAreaView edges={["top"]} style={{ flex: 1, backgroundColor: "#000" }}>
      <TopReelTab.Navigator
        initialRouteName="Foryou"
        screenOptions={({ route }) => ({
          tabBarPressColor: "black",
          tabBarPressVisible: true,
          // 自定义动画Logo头部
          header: () => (
            <Animated.View
              style={{
                transform: [{ translateY: topBarTranslateY }],
                height: 45,
                justifyContent: "center",
                backgroundColor: "#000",
              }}
            >
              <Animated.Image
                source={require(".././assets/images/test/Logo.png")}
                style={{
                  alignSelf: "center",
                  width: 45,
                  height: 45,
                  opacity: topBarTranslateY.interpolate({
                    inputRange: [-TOP_BAR_TOTAL_HEIGHT, 0],
                    outputRange: [0, 1],
                  }),
                }}
              />
            </Animated.View>
          ),
          tabBarLabel: ({ focused }) => {
            return (
              <MaskedView
                maskElement={
                  <Text fontWeight="bold" fontSize={18}>
                    {route.name}
                  </Text>
                }
              >
                <LinearGradient
                  colors={["#E53AD9", "#FF630B"]}
                  start={{ x: 0, y: 0.4 }}
                  end={{ x: 1, y: 0.6 }}
                >
                  <Text
                    fontSize={18}
                    fontWeight="bold"
                    color={focused ? "transparent" : "white"}
                  >
                    {route.name}
                  </Text>
                </LinearGradient>
              </MaskedView>
            );
          },
          tabBarIndicatorStyle: {
            backgroundColor: "#E53AD9",
            alignSelf: "center",
          },
          // 动画TabBar位置
          tabBarStyle: {
            backgroundColor: "#000",
            transform: [{ translateY: topBarTranslateY }],
          },
          // 动态调整内容paddingTop,适配顶部栏显示/隐藏
          contentStyle: {
            paddingTop: topBarTranslateY.interpolate({
              inputRange: [-TOP_BAR_TOTAL_HEIGHT, 0],
              outputRange: [0, TOP_BAR_TOTAL_HEIGHT],
            }),
          },
        })}
      >
        <TopReelTab.Screen name="Following">
          {(props) => (
            <ReelFollowingScreen
              {...props}
              setScrollDirection={setScrollDirection}
            />
          )}
        </TopReelTab.Screen>
        <TopReelTab.Screen name="Foryou">
          {(props) => (
            <ReelForyouScreen
              {...props}
              setScrollDirection={setScrollDirection}
            />
          )}
        </TopReelTab.Screen>
      </TopReelTab.Navigator>
    </SafeAreaView>
  );
}

2. 修改ReelForyouScreen:移除固定高度,自适应容器

删除子页面中固定的height设置,让内容自适应父容器高度:

export default function ReelForyouScreen({
  navigation,
  setScrollDirection,
}: Props): JSX.Element {
  // ... 其他代码保持不变

  return (
    <Box bg="blue.900" flex={1}> {/* 移除height={height + 60},改用flex:1自适应 */}
      <FlashList
        ref={flashListRef}
        data={data?.events as Event[]}
        extraData={index}
        renderItem={({ item }) => verification(item)}
        estimatedItemSize={500}
        maxToRenderPerBatch={5}
        updateCellsBatchingPeriod={100}
        windowSizeprop={5}
        keyExtractor={(item) => item.id}
        onViewableItemsChanged={onViewableItemsChanged}
        viewabilityConfig={{
          itemVisiblePercentThreshold: 70,
        }}
        onScroll={handleScroll}
      />
    </Box>
  );
}

核心改进点

  • 仅对顶部栏(Logo+TabBar)执行动画,页面内容区域保持原位,避免整体上移
  • 通过contentStyle动态调整内容的paddingTop,顶部栏隐藏时自动填充空白区域
  • 移除子页面固定高度设置,确保内容始终填满容器,消除底部黑条

内容的提问来源于stack exchange,提问作者matsoccer 360

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 06:28:09