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

如何使用React Navigation实现中间凸起的底部标签按钮?

React Navigation v6 凸起底部标签导航实现方案

你要实现的效果参考:
示例效果

方案选择参考

  • 方案1(定制第三个标签按钮):适合中间按钮点击后需要切换到对应Tab页面(也就是你的Premium页面)的场景,逻辑和原生Tab导航完全对齐,实现成本最低
  • 方案2(4个标签+中间悬浮按钮):适合中间按钮点击后不切换Tab、而是弹出菜单/跳转独立页面的场景,灵活性更高

方案1 实现代码

无需改动现有Tab的数量结构,只需要给Tab.Navigator添加全局样式配置,给第三个Premium标签自定义按钮渲染逻辑即可:

import * as React from 'react';
import { Text, View, TouchableOpacity, StyleSheet, Platform } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
// 示例用图标库,可替换为自己的图标资源
import { Ionicons } from '@expo/vector-icons';

// 补全你的页面组件
function ForYouScreen() {
  return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>ForYou!</Text></View>;
}
function MapsScreen() {
  return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Maps!</Text></View>;
}
function PremiumScreen() {
  return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Premium!</Text></View>;
}
function ShopScreen() {
  return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Shop!</Text></View>;
}
function MediaScreen() {
  return <View style={{ flex: 1, justifyContent: 'center', alignItems: 'center' }}><Text>Media!</Text></View>;
}

const Tab = createBottomTabNavigator();

export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={({ route }) => ({
          // 隐藏头部
          headerShown: false,
          // Tab栏基础样式
          tabBarStyle: styles.tabBar,
          tabBarShowLabel: true,
          tabBarActiveTintColor: '#6200ee',
          tabBarInactiveTintColor: '#666',
          // 普通Tab的图标
          tabBarIcon: ({ focused, color, size }) => {
            let iconName;
            if (route.name === 'ForYou') iconName = focused ? 'heart' : 'heart-outline';
            else if (route.name === 'Maps') iconName = focused ? 'map' : 'map-outline';
            else if (route.name === 'Shop') iconName = focused ? 'cart' : 'cart-outline';
            else if (route.name === 'Media') iconName = focused ? 'play-circle' : 'play-circle-outline';
            else if (route.name === 'Premium') iconName = focused ? 'star' : 'star-outline';
            return <Ionicons name={iconName} size={route.name === 'Premium' ? 28 : size} color={color} />;
          },
        })}
      >
        <Tab.Screen name="ForYou" component={ForYouScreen} />
        <Tab.Screen name="Maps" component={MapsScreen} />
        <Tab.Screen 
          name="Premium" 
          component={PremiumScreen}
          options={{
            // 自定义凸起按钮
            tabBarButton: ({ children, onPress }) => (
              <TouchableOpacity
                style={styles.premiumButton}
                onPress={onPress}
              >
                {children}
              </TouchableOpacity>
            ),
            tabBarLabel: () => null, // 隐藏中间按钮的文字
          }}
        />
        <Tab.Screen name="Shop" component={ShopScreen} />
        <Tab.Screen name="Media" component={MediaScreen} />
      </Tab.Navigator>
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  tabBar: {
    height: Platform.OS === 'ios' ? 85 : 65,
    paddingBottom: Platform.OS === 'ios' ? 20 : 10,
    paddingTop: 10,
    backgroundColor: '#fff',
    borderTopWidth: 1,
    borderTopColor: '#eee',
  },
  premiumButton: {
    top: -20,
    justifyContent: 'center',
    alignItems: 'center',
    width: 60,
    height: 60,
    borderRadius: 30,
    backgroundColor: '#fff',
    shadowColor: '#6200ee',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 8,
  }
});

方案2 实现代码

如果需要中间按钮不和Tab导航绑定,只做独立操作,就可以用4个Tab+中间悬浮按钮的方案:

  1. 首先把Tab的数量改为4个,左右各2个
  2. 自定义Tab栏的布局,给中间预留出悬浮按钮的位置
  3. 添加绝对定位的悬浮按钮覆盖在中间位置
// 其他导入和页面组件和上面一致
export default function App() {
  return (
    <NavigationContainer>
      <Tab.Navigator
        screenOptions={{
          headerShown: false,
          tabBarStyle: styles.tabBar,
          tabBarActiveTintColor: '#6200ee',
          tabBarInactiveTintColor: '#666',
          tabBarItemStyle: { width: '22%' }, // 四个Tab每个占22%宽度,剩下12%留作中间位置
        }}
      >
        <Tab.Screen name="ForYou" component={ForYouScreen} />
        <Tab.Screen name="Maps" component={MapsScreen} />
        <Tab.Screen name="Shop" component={ShopScreen} />
        <Tab.Screen name="Media" component={MediaScreen} />
      </Tab.Navigator>
      {/* 中间悬浮按钮 */}
      <TouchableOpacity 
        style={styles.floatButton}
        onPress={() => {
          // 自定义点击逻辑,比如弹出弹窗、跳转独立页面等
          alert('点击了Premium按钮');
        }}
      >
        <Ionicons name="star" size={28} color="#6200ee" />
      </TouchableOpacity>
    </NavigationContainer>
  );
}

const styles = StyleSheet.create({
  tabBar: {
    height: Platform.OS === 'ios' ? 85 : 65,
    paddingBottom: Platform.OS === 'ios' ? 20 : 10,
    paddingTop: 10,
    paddingHorizontal: '2%',
    backgroundColor: '#fff',
    borderTopWidth: 1,
    borderTopColor: '#eee',
  },
  floatButton: {
    position: 'absolute',
    bottom: Platform.OS === 'ios' ? 45 : 35,
    alignSelf: 'center',
    width: 60,
    height: 60,
    borderRadius: 30,
    backgroundColor: '#fff',
    justifyContent: 'center',
    alignItems: 'center',
    shadowColor: '#6200ee',
    shadowOffset: { width: 0, height: 4 },
    shadowOpacity: 0.3,
    shadowRadius: 4,
    elevation: 8,
  }
});

注意事项

  • 所有样式数值可以根据你的设计稿灵活调整,凸起高度、圆角、图标大小、颜色都可以自定义
  • 如果需要适配不同尺寸的设备,可以用react-native-size-matters等库做响应式尺寸适配
  • 图标可以直接替换为你自己的设计资源,不需要依赖第三方图标库

内容的提问来源于stack exchange,提问作者Guille Acosta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 09:24:02