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

createMaterialBottomTabNavigator在iOS异常:点击水波纹效果失效

解决iOS端react-navigation-material-bottom-tabs无波纹点击效果的问题

这个问题本质是Material Design的波纹效果是Android平台的原生特性,iOS系统本身没有对应的默认交互反馈,所以react-navigation-material-bottom-tabs默认在iOS上不会渲染波纹。不过我们可以通过自定义标签栏组件的方式,手动给iOS添加一致的波纹点击效果,下面是具体实现步骤:

步骤1:引入必要组件

首先需要从react-native-paper导入TouchableRipple组件,它能帮我们实现跨平台的波纹点击效果,同时保留原库的MaterialBottomTabBar用于Android端:

import { TouchableRipple } from 'react-native-paper';
import { createMaterialBottomTabNavigator, MaterialBottomTabBar } from 'react-navigation-material-bottom-tabs';
import { Platform, View } from 'react-native';

步骤2:自定义TabBar组件

我们重写标签栏组件,仅在iOS平台替换为带波纹的点击容器,Android平台保留原生效果:

const CustomTabBar = props => {
  if (Platform.OS === 'ios') {
    return (
      <View style={{ flexDirection: 'row', backgroundColor: props.shifting ? props.navigation.state.routes[props.navigation.state.index].params?.tabBarColor : 'transparent' }}>
        {props.navigation.state.routes.map((route, index) => {
          const isActive = index === props.navigation.state.index;
          const { options } = props.descriptors[route.key];
          const icon = options.tabBarIcon({ tintColor: isActive ? props.activeColor : props.inactiveColor });
          const tabBarColor = options.tabBarColor || 'gray';

          return (
            <TouchableRipple
              key={route.key}
              onPress={() => props.jumpTo(route.routeName)}
              rippleColor="rgba(255,255,255,0.3)"
              style={{ flex: 1, justifyContent: 'center', alignItems: 'center', paddingVertical: 8, backgroundColor: isActive && props.shifting ? tabBarColor : 'transparent' }}
            >
              <View style={{ alignItems: 'center' }}>
                {icon}
              </View>
            </TouchableRipple>
          );
        })}
      </View>
    );
  }
  // Android端使用原生TabBar,保留系统波纹
  return <MaterialBottomTabBar {...props} />;
};

步骤3:修改Navigator配置

在你的导航配置中添加自定义标签栏的引用:

const config = {
  headerMode: 'none',
  initialRouteName: 'Screen1',
  shifting: true,
  activeColor: 'white',
  inactiveColor: 'black',
  tabBarComponent: CustomTabBar // 新增这一行
};

完整修改后的代码

把以上内容整合到你的原代码中,最终代码如下:

import * as React from 'react';
import { View, Platform } from 'react-native';
import Screen1 from './Screen1';
import Screen2 from './Screen2';
import { createAppContainer } from 'react-navigation';
import { createMaterialBottomTabNavigator, MaterialBottomTabBar } from 'react-navigation-material-bottom-tabs';
import { MaterialIcons } from '@expo/vector-icons';
import { TouchableRipple } from 'react-native-paper';

const tabBarIcon = name => ({ tintColor }) => (
  <MaterialIcons style={{ backgroundColor: 'transparent' }} name={name} color={tintColor} size={24} />
);

const CustomTabBar = props => {
  if (Platform.OS === 'ios') {
    return (
      <View style={{ flexDirection: 'row', backgroundColor: props.shifting ? props.navigation.state.routes[props.navigation.state.index].params?.tabBarColor : 'transparent' }}>
        {props.navigation.state.routes.map((route, index) => {
          const isActive = index === props.navigation.state.index;
          const { options } = props.descriptors[route.key];
          const icon = options.tabBarIcon({ tintColor: isActive ? props.activeColor : props.inactiveColor });
          const tabBarColor = options.tabBarColor || 'gray';

          return (
            <TouchableRipple
              key={route.key}
              onPress={() => props.jumpTo(route.routeName)}
              rippleColor="rgba(255,255,255,0.3)"
              style={{ flex: 1, justifyContent: 'center', alignItems: 'center', paddingVertical: 8, backgroundColor: isActive && props.shifting ? tabBarColor : 'transparent' }}
            >
              <View style={{ alignItems: 'center' }}>
                {icon}
              </View>
            </TouchableRipple>
          );
        })}
      </View>
    );
  }
  return <MaterialBottomTabBar {...props} />;
};

const screens = {
  Screen1: {
    screen: Screen1,
    navigationOptions: {
      tabBarIcon: tabBarIcon('photo-album'),
      tabBarColor: 'blue'
    }
  },
  Screen2: {
    screen: Screen2,
    navigationOptions: {
      tabBarIcon: tabBarIcon('favorite'),
      tabBarColor: 'green'
    }
  }
};

const config = {
  headerMode: 'none',
  initialRouteName: 'Screen1',
  shifting: true,
  activeColor: 'white',
  inactiveColor: 'black',
  tabBarComponent: CustomTabBar
};

const MainNavigator = createMaterialBottomTabNavigator(screens, config);
export default createAppContainer(MainNavigator);

补充说明

  • 我们通过Platform.OS区分平台,iOS用自定义波纹组件,Android保留原生Material Design波纹,兼顾平台特性和交互一致性。
  • 可以通过调整TouchableRipple的rippleColor属性,自定义波纹的颜色和透明度,适配你的UI风格。
  • 针对shifting: true的模式,我们同步了标签切换时的背景色变化,和原组件的行为保持一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 07:12:01