从一个组件修改Tab Bar的值(react-navigation 6)

Modify the value of the Tab Bar from a component (react-navigation 6)

我正在尝试在我的 React Native 应用程序中实现颜色自定义功能。

我使用 AsyncStorage 存储两个值,主要颜色和次要颜色。每当我加载一个组件时,我都会在 ComponentDidMount() 中调用一个函数来获取这两个值并更新状态(我的状态默认情况下将 mainColorsecondaryColor 设置为 undefined,然后它会更新为新值),并且我的屏幕组件会以正确的颜色呈现。这部分代码工作得很好,但我把它放在这里是为了让您了解一些上下文。 (如果您认为这效率低下,或者您知道更好的方法,请随时告诉我)

我的问题是我还有一个带有图标的 header 按钮,我希望图标的颜色由 AsyncStorage 存储的值 mainColor 定义。

我的 header 按钮在我的 App.js 文件中定义,它管理所有导航系统(我使用的是 React Navigation 6):

// App.js

import { StatusBar } from 'expo-status-bar';
import React from "react";
import { StyleSheet, Image, TouchableOpacity } from "react-native";
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import { createBottomTabNavigator } from '@react-navigation/bottom-tabs';

import Counter from './components/Counter.js';
import AddCounter from './components/AddCounter.js';

// Translation module
import * as Localization from 'expo-localization';
import i18n from 'i18n-js';
import { en, fr } from './i18n/supportedLanguages';
i18n.fallbacks = true;
i18n.translations = { en, fr };
i18n.locale = Localization.locale;

const Stack = createStackNavigator();
const Tab = createBottomTabNavigator();


// All components managed by TabBar
function TabBar() {
  return (
    <Tab.Navigator
      screenOptions={ ({route}) => ({
        tabBarActiveBackgroundColor: "#DDDDDD",
        tabBarInactiveBackgroundColor: "#FFFFFF",
        tabBarShowLabel: false,
        tabBarShowIcon: true
      })}>
      <Tab.Screen
        name="CounterTab"
        component={Counters}
        options= {{
          headerShown: false,
          tabBarIcon: () => {
            return (
              <Image
                tintColor="#000000"
                source={require("./assets/add_counter.png")}
                style={styles.icon}
              />
            )
          }
        }} />
    </Tab.Navigator>
  )
}

// Everything inside the "Counter" tab, which should display the tab bar
function Counters() {
  return (
    <Stack.Navigator>
      <Stack.Screen
        name="Counter"
        component={Counter}
        options={({navigation}) => ({
          title: i18n.t('counters.header_text'),
          headerRight: () => (
            <TouchableOpacity
              style={styles.add_counter_header}
              onPress={() => navigation.navigate('AddCounter')}>

              <Image
                style={styles.add_counter_button}
                tintColor="#000000"                // <- THE VALUE I WANTED TO BE CUSTOMIZABLE
                source={require("./assets/add_counter.png")}/>

            </TouchableOpacity>
          )
        })} />
    </Stack.Navigator>
  )
}

export default function App() {
  return (
    <NavigationContainer>
      <Stack.Navigator>

        {/*TabBar display*/}

        <Stack.Screen
          name="TabBar"
          component={TabBar}
          options={{
            headerShown: false
          }} />

        {/*FROM HERE : every screen that shouldn't display the TabBar*/}

        <Stack.Screen
          name="AddCounter"
          component={AddCounter}
          options={{
            title: i18n.t('add_counters.header_text'),
            tabBarStyle: { display: 'none' }
          }} />

      </Stack.Navigator>
    </NavigationContainer>
  )
}

const styles = StyleSheet.create({
  icon: {
    width: 30,
    height: 30,
  },
  add_counter_header: {
    marginRight: 10
  },
  add_counter_button: {
    height: 26,
    width: 26
  }
});

我首先想到我应该尝试获取 mainColor 的值,然后呈现应用程序,但我没有设法让它工作,所以我记录了自己并找到了另一种方法:我加载使用 header 图标的默认颜色(在这种情况下为“#000000”)的应用程序,然后在检索到值后,我从计数器组件修改它。

这是我所做的:

// Counter.js, the screen that is first rendered when the app launch, and that have an header button

componentDidMount() {

    ( async () => {

      await this._getColors() // this function updates the state with the color values
      this.props.navigation.setOptions({
        headerRight: () => (
          <TouchableOpacity
            style={styles.add_counter_header}
            onPress={() => navigation.navigate('AddCounter')}>

            <Image
              style={styles.add_counter_button}
              tintColor={this.state.mainColor}  // <- I set the color of the header button here
              source={require("../assets/add_counter.png")}/>

          </TouchableOpacity>
        )
      });

    })()
}

同样,这工作正常,我有 header 按钮,颜色我定义为 mainColor

还有一件事是我想做的:自定义 TabBar 图标的颜色,就像我对 Header 按钮所做的那样。这就是我遇到问题的地方:我不知道如何从我的组件访问它,而且我在互联网上发现的唯一响应类似问题的东西已经过时了。有人知道我该怎么做吗?

如果我的问题表达不正确,我很抱歉,这是我 post 在这个网站上的第一个问题。如有必要,请随时告诉我如何 post 一个好问题。如果你在我的代码中看到一些可怕的东西(一些编码错误的东西)不要犹豫告诉我,我是 React Native 的新手。

感谢您阅读本文:)

我猜你有多个导航级别,所以你可以使用 navigation.getParent() 函数到达另一个导航级别 (https://reactnavigation.org/docs/navigation-prop#getparent)

所以在你的情况下应该是:

navigation.getParent().setOptions({..})

另一种实现该行为的方法是将您的颜色值存储在上下文中,然后所有导航器都可以到达该上下文以应用这些颜色。