I want to implement a function to change the overall color of the app (navigation head, tabBar and buttons), such as changing to black at night to protect the eyes, or choose the user’s favorite color.

First put the concrete realization effect diagram:


The overall train of thought

  1. In app.js, add a global variable screenProps and place the color variable in it. Then add the listener. When the color changes, the listener will be triggered to change the color value in state until the color is re-rendered.
  2. In the Router configuration file, the configuration color is obtained from screenProps.
  3. The skin page calls the replace color method, triggering the listen.

Core dependency version

"The react - native" : "0.60.5", "the react - navigation" : "^ 3.11.1." "Copy the code


The specific implementation

One, the entry file to add global variables and listen

/ * * * Created by supervons 2019/08/02 App entry file * * * App entry file * * * * https://github.com/supervons/ExploreRN@format
 * @flow* /

import React, { Component } from 'react';

// Navigate the routing table
import RootStack from './src/routers/index';
import { View, DeviceEventEmitter } from 'react-native';
export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      color: '#f4511E'
    };
  }

  componentDidMount() {
    // Add a global listener for color changes
    DeviceEventEmitter.addListener('theme_change'.params= > {
      this.setState({
        color: params
      });
    });
  }

  render(): * {
    return (
          <View style={{ flex: 1}} >
            <RootStack
              screenProps={{
                themeColor: this.state.color}} / >
          </View>); }}Copy the code

In this case, it is the route configuration, which will be changed in the next step.

Second, modify the router configuration file

const Tabs = createMaterialTopTabNavigator(
  {
    MainPage: {
      screen: MainPage,
      navigationOptions: ({ navigation, screenProps }) = > ({
        // Use screenProps. ThemeColor instead. })}})const Router = createStackNavigator(
  {
    Login: {
      // Login screen
      screen: Login
    },
    MainPage: {
      screen: Tabs
    }
  },
  {
    // Define the configuration
    initialRouteName: 'Login'.// Set the initial route to the login page
    headerMode: 'screen'.defaultNavigationOptions: ({ navigation, screenProps }) = > ({
      // screenProps gets the global variable themeColor
      headerStyle: {
        backgroundColor: screenProps.themeColor // <----- Look here
      },
      headerTintColor: '#ffffff'.headerTitleStyle: {
        fontWeight: 'bold'}})});Copy the code

Three, call the method on the page, triggering the listener

DeviceEventEmitter.emit('theme_change'.'black');
Copy the code

Yes, you read that right, one line of code triggered the peels.

Of course, if you want to keep the peel, you’ll need to store it in the background database, and then the next time the user enters the app and pulls the configuration from the background, you’ll have a permanent peel.


The project address

Github.com/supervons/E… Welcome to star~