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
相关产品推荐
相关产品推荐

