createMaterialBottomTabNavigator在iOS异常:点击水波纹效果失效
这个问题本质是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
相关产品推荐
相关产品推荐

