React Navigation(v5):特定标签屏幕的自定义标题按钮

时间:2020-04-10 13:19:40

标签: react-native react-navigation react-navigation-v5

我需要在标签导航中的标题上放置按钮。每个选项卡的标题中可以有不同的按钮,并且这些按钮需要与屏幕本身进行交互。例如,在我的旅行应用程序中,在第一个选项卡中,我将在标题中具有地图按钮,这将切换地图/列表视图,而在愿望清单选项卡中,我将具有标题中的加号按钮。

当它是标准屏幕(不是选项卡)时,添加一个与屏幕交互的按钮很容易,可以按照https://reactnavigation.org/docs/header-buttons#header-interaction-with-its-screen-component中的说明进行操作。但是,这不适用于选项卡下的屏幕。我找到了https://reactnavigation.org/docs/screen-options-resolution的文档,该文档说明了如何在标签导航中更改标题和样式,但是由于定义标签的组件是,所以我找不到有关如何以与屏幕交互的方式添加按钮的任何信息。与屏幕组件不同。

1 个答案:

答案 0 :(得分:-1)

您可以在react-navigation V5中使用prop:“ tabBar”添加Tab Bar组件。您可以这样:

<Tab.Navigator
          animationEnabled={false}
          swipeEnabled={true}
          tabBar={props => <TabBarComp {...props} />}
          tabBarOptions={{
            // scrollEnabled: true,
            activeTintColor: '#3684F6', //'rgb(12,157,197)',
            inactiveTintColor: 'black',
            indicatorStyle: {
              backgroundColor: '#ACACAC',
            },
            labelStyle: {
              fontSize: 16,
              color: 'black',
            },
            style: {
              backgroundColor: 'white',
            },
            statusBarStyle: 'light-content',
          }}>
        
                  <Tab.Screen name={'tabName} component={screenName} />
        </Tab.Navigator>

我也在做同样的事情,“我的标签栏组件”看起来像这样:

import React from 'react';
import {View, TouchableOpacity, ScrollView, Dimensions} from 'react-native';
import Animated from 'react-native-reanimated';
import {colors, fonts} from '../../res';
import {setValueBasedOnHeight, setFontSize} from '../../utils/deviceDimensions';

export const TabBarComp = ({state, descriptors, navigation, position}) => {
  const isIpad = Dimensions.get('window').width > 500 ? true : false;
  return (
    <View>
      <ScrollView
        showsHorizontalScrollIndicator={false}
        horizontal
        style={{
          width: '100%',
          backgroundColor: colors.white,
        }}
        contentContainerStyle={{
          flexGrow: 1,
        }}>
        {state.routes.map((route, index) => {
          const {options} = descriptors[route.key];
          console.log({options});
          const label =
            options.tabBarLabel !== undefined
              ? options.tabBarLabel
              : options.title !== undefined
              ? options.title
              : route.name;

          console.log({label});

          const isFocused = state.index === index;
          console.log({isFocused});
          const onPress = () => {
            const event = navigation.emit({
              type: 'tabPress',
              target: route.key,
              canPreventDefault: true,
            });
            console.log('route.name', route.name);
            if (!isFocused && !event.defaultPrevented) {
              navigation.navigate(route.name);
            }
          };

          const inputRange = state.routes.map((_, i) => i);
          const opacity = Animated.interpolate(position, {
            inputRange,
            outputRange: inputRange.map(i => (i === index ? 1 : 0.5)),
          });

          return (
            <TouchableOpacity
              accessibilityRole="button"
              accessibilityStates={isFocused ? ['selected'] : []}
              accessibilityLabel={options.tabBarAccessibilityLabel}
              testID={options.tabBarTestID}
              onPress={onPress}
              style={{
                backgroundColor: colors.whiteColor,
                borderBottomColor: colors.grayColor,
                borderBottomWidth: isFocused ? 0.5 : 0,
                flex: 1,
                justifyContent: 'center',
              }}>
              <Animated.Text
                style={{
                  color: colors.grayColor,
                  fontSize: setFontSize(14),
                  paddingHorizontal: 20,
                  alignSelf: 'center',
                  fontFamily: fonts.avenirNextBold,
                  paddingVertical: 10,
                  minWidth: '35%',
                  opacity,
                }}>
                {label}
              </Animated.Text>
            </TouchableOpacity>
          );
        })}
      </ScrollView>
    </View>
  );
};

this.props.navigation.setOptions({
      headerTitle: (
        <Text
          style={[
            {color: 'white'},
            {fontSize: 22},
            {fontFamily: fonts.avenirNextDemiBold},
          ]}>
          Privacy Policy
        </Text>
      ),
      headerStyle: {
        borderBottomWidth: 0,
        backgroundColor: colors.navBarHeaderColor,
      },
      headerTintColor: colors.whiteColor,
    });