在 React Navigation 默认主题中扩展颜色

时间:2021-03-08 20:29:45

标签: reactjs react-native themes react-navigation

我在我的应用中使用 React Navigation Default 和 Dark 主题。用户可以通过切换按钮更改主题,一切正常。

现在我想为默认和深色主题添加其他颜色。 所以默认情况下,他们有类似的东西:

Object {
  "background": "rgb(1, 1, 1)",
  "border": "rgb(39, 39, 41)",
  "card": "rgb(18, 18, 18)",
  "notification": "rgb(255, 69, 58)",
  "primary": "rgb(10, 132, 255)",
  "text": "rgb(229, 229, 231)",
}

我想做的是附加如下内容:

"commentText": "rgb(200, 200, 100)"

我目前以这种方式调用主题:

import { useTheme } from "@react-navigation/native";
const { colors } = useTheme();
  const styles = StyleSheet.create({
    text: {
      fontSize: 16,
      color: colors.text,
    },
  });

// in my component ...

<Text style={styles.text}>Date format</Text>

最好的方法是什么?我是否需要完全定义自己的自定义主题,包含原始颜色和我的颜色?有什么方法可以简单地附加到原始内容上?

更新:

我部分关注了 this guide 并决定创建我自己的主题并添加更多条目(在这篇文章中不可见)。 现在我当前的挑战是直接在定义我的样式的文件中移动颜色定义(例如 typography.js)。如果我使用定义的颜色(例如 border: "#d8d8d8"),它工作正常,但我希望它选择主题(例如 color: colors.text)。

问题是 useTheme() 只能在 React 函数组件或自定义 React Hook 函数中调用。 例如,我如何在 typography.js 中使用它?

下面提供的代码,请注意评论。

Home.js

import { useTheme } from "@react-navigation/native";
import React, { useContext, useEffect, useState } from "react";
import {
  Dimensions,
  StyleSheet,
  Text,
  TouchableOpacity,
  View,
} from "react-native";

import { borders, buttons, layout, typography } from "../styles";

const Home = ({ navigation }) => {

  const { colors } = useTheme();

  const styles = StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: colors.background  // Works fine
    },
    buttonText: {
      ...typography.buttonText,
      color: colors.text,      // I would like to move this to typography.js
    }
  });

  return (
    <>
      <View style={styles.container}>
        <Text style={styles.buttonText}>blabla</Text>
        // More code here....
      </View>
    </>
  );
};

export default Home;

./styles/index.js

import * as themes from "./themes";
import * as typography from "./typography";

export {
  themes,
  typography
};

./styles/themes.js

export const MyDefaultTheme = {
  dark: false,
  colors: {
    background: "#f2f2f2",
    border: "#d8d8d8", 
    card: "#ffffff", 
    notification: "#ff3b30",
    primary: "#007aff", 
    text: "#1c1c1e", 
  },
};

export const MyDarkTheme = {
  dark: true,
  colors: {
    background: "#010101", 
    border: "#272729", 
    card: "#121212",
    notification: "#ff453a", 
    primary: "#0a84ff", 
    text: "#e5e5e7", 
  },
};

./styles/typography.js

import { useTheme } from "@react-navigation/native"; // // This isn't working
const { colors } = useTheme(); // This isn't working

export const textHeader = {
  fontWeight: "bold",
  fontSize: 30,
  textAlign: "center",
  marginBottom: 20,
};

export const buttonText = {
  fontSize: 14,
  textAlign: "center",
  color: colors.text  // This is not working 
};

2 个答案:

答案 0 :(得分:0)

您正在寻找的是 Appearance API。限制是鼓励您使用内联样式,因为主题可能会改变,例如从白天到黑夜。

在您的示例代码中,您在组件外部调用 useTheme(),因此它不会工作。您的内联颜色样式的原始解决方案似乎正是 React Native 团队推荐的。

答案 1 :(得分:-2)

您需要在 Redux 中存储一个 Value,并且在此 Value 的基础上,您可以通过在每个组件中获取此值来更改每个组件的颜色。
只需在 App.js 中调度 action 并根据存储在 redux 中的值应用自定义颜色。

    useEffect(() => {
    subscription = Appearance.addChangeListener(({ colorScheme }) => {
        if (colorScheme === 'light') {
            dispatch(setMode(false));
        } else {
            dispatch(setMode(true));
        }
    });
    return () => subscription && subscription.remove();
}, []);
相关问题