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

React Native 如何实现底部带弧度的复杂自定义 Tab Bar

React Native 带中心弧度凸起TabBar实现方案

实现思路

要做到响应式适配,核心是避免硬编码固定宽高数值,所有布局参数基于当前设备的屏幕尺寸、安全边距动态计算,弧度区域用SVG绘制适配不同屏幕宽度。

依赖准备

需要提前安装以下依赖:

  • 导航相关:@react-navigation/native、@react-navigation/bottom-tabs
  • SVG绘制相关:react-native-svg、react-native-svg-transformer
    安装完成后需要配置metro.config.js支持SVG导入,配置示例:
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');

module.exports = mergeConfig(getDefaultConfig(__dirname), {
  transformer: {
    babelTransformerPath: require.resolve('react-native-svg-transformer'),
  },
  resolver: {
    assetExts: getDefaultConfig(__dirname).resolver.assetExts.filter(ext => ext !== 'svg'),
    sourceExts: [...getDefaultConfig(__dirname).resolver.sourceExts, 'svg'],
  },
});

自定义TabBar核心实现

直接替换@react-navigation/bottom-tabs默认的TabBar组件,示例代码如下:

import { View, TouchableOpacity, Text, useWindowDimensions } from 'react-native';
import { Svg, Path } from 'react-native-svg';
import { useSafeAreaInsets } from 'react-native-safe-area-context';

const ArcTabBar = ({ state, descriptors, navigation }) => {
  // 动态获取当前屏幕宽度,适配横竖屏、不同尺寸设备
  const { width: screenWidth } = useWindowDimensions();
  // 获取底部安全边距,适配全面屏、非全面屏设备
  const { bottom: bottomInset } = useSafeAreaInsets();
  
  const tabBarBaseHeight = 60;
  const tabBarTotalHeight = tabBarBaseHeight + bottomInset;
  const centerBulgeHeight = 22; // 中心凸起高度可自定义

  // 基于屏幕宽度动态计算SVG弧度路径
  const tabBarPath = `
    M0,0
    L${screenWidth/2 - 55},0
    Q${screenWidth/2 - 30},0 ${screenWidth/2 - 25},${centerBulgeHeight}
    Q${screenWidth/2},${centerBulgeHeight * 2} ${screenWidth/2 + 25},${centerBulgeHeight}
    Q${screenWidth/2 + 30},0 ${screenWidth/2 + 55},0
    L${screenWidth},0
    L${screenWidth},${tabBarTotalHeight}
    L0,${tabBarTotalHeight}
    Z
  `;

  return (
    <View style={{ position: 'absolute', bottom: 0, width: screenWidth }}>
      {/* 绘制带弧度的TabBar背景 */}
      <Svg width={screenWidth} height={tabBarTotalHeight} style={{ position: 'absolute' }}>
        <Path 
          d={tabBarPath} 
          fill="#ffffff" 
          shadowColor="#000000"
          shadowOffset={{ width: 0, height: -3 }}
          shadowOpacity={0.12}
          shadowRadius={5}
        />
      </Svg>
      {/* 渲染Tab按钮 */}
      {state.routes.map((route, index) => {
        const isCenterTab = index === Math.floor(state.routes.length / 2);
        const tabWidth = screenWidth / state.routes.length;
        return (
          <TouchableOpacity
            key={route.key}
            style={{
              position: 'absolute',
              top: isCenterTab ? -centerBulgeHeight : 12,
              left: tabWidth * index + tabWidth/2 - 24,
              alignItems: 'center',
              paddingBottom: isCenterTab ? 0 : bottomInset
            }}
            onPress={() => navigation.navigate(route.name)}
          >
            {/* 此处替换为你自己的Tab图标、文字即可 */}
            <Text style={{ color: state.index === index ? '#2563eb' : '#64748b' }}>
              {route.name}
            </Text>
          </TouchableOpacity>
        )
      })}
    </View>
  )
}

// 导航中使用自定义TabBar
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';
const Tab = createBottomTabNavigator();

const AppNavigator = () => {
  return (
    <Tab.Navigator tabBar={props => <ArcTabBar {...props} />}>
      {/* 配置你的Tab页面 */}
      <Tab.Screen name="首页" component={HomeScreen} />
      <Tab.Screen name="分类" component={CategoryScreen} />
      <Tab.Screen name="发布" component={PublishScreen} />
      <Tab.Screen name="消息" component={MessageScreen} />
      <Tab.Screen name="我的" component={MineScreen} />
    </Tab.Navigator>
  )
}

适配注意事项

  • 所有尺寸参数都基于动态获取的屏幕宽度、安全边距计算,无需适配不同设备的硬编码数值
  • 如需适配横竖屏切换,无需额外处理,useWindowDimensions会自动监听宽度变化更新路径
  • 弧度的弯曲程度可以通过调整Path路径里的贝塞尔曲线参数自定义,调整到和设计图一致即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.23 21:06:01