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

问题描述 投票:0回答:3

我在我的应用程序中使用 React Navigation 默认和深色主题。用户可以通过“切换”按钮更改主题,一切正常。

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

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>

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

更新:

我部分遵循了本指南,并决定创建自己的主题并添加更多条目(在本文中不可见)。 现在我当前的挑战是直接在定义样式的文件中移动颜色定义(例如

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 
};
reactjs react-native themes react-navigation
3个回答
0
投票

您正在寻找的是外观API。限制是鼓励您使用内联样式,因为主题可能会发生变化,例如从白天切换到晚上。

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


0
投票

我在最近的应用程序中也遇到了类似的问题。不幸的是,我发现不可能根据 React 组件之外的主题获取

colors
的动态值,例如在
colors.js
等实用程序文件中。

因此,为了解决这个问题,我的方法是使用

makeStyles
函数,根据传递给它的主题或颜色动态生成样式。 这使我能够保持样式模块化,并确保可以在应用程序中一致地使用主题颜色,而无需直接将
useTheme
导入到样式文件中。

以下是实施方法:


解决方案:创建一个
makeStyles
实用程序

  1. 创建
    makeStyles
    函数
    该函数采用主题或颜色作为参数并动态返回样式。
import { StyleSheet } from "react-native";

const makeStyles = (theme) => {
  const { colors } = theme;

  return StyleSheet.create({
    container: {
      flex: 1,
      backgroundColor: colors.background, // using background color from theme
    },
    buttonText: {
      fontSize: 14,
      textAlign: "center",
      color: colors.text, // using text color from theme
    },
    textHeader: {
      fontWeight: "bold",
      fontSize: 30,
      textAlign: "center",
      marginBottom: 20,
      color: colors.primary, // using primary color from theme
    },
  });
};

export default makeStyles;

  1. 将主题传递给组件中的

    makeStyles

    在组件内使用

    useTheme
    获取当前主题并将其传递给
    makeStyles

import { useTheme } from "@react-navigation/native";
import React, { useMemo } from "react";
import { Text, View } from "react-native";
import makeStyles from "../styles/makeStyles";

const Home = () => {
  const { colors } = useTheme();

  // Memoize the styles to avoid unnecessary re-creations
  const styles = useMemo(() => makeStyles({ colors }), [colors]);

  return (
    <View style={styles.container}>
      <Text style={styles.textHeader}>Welcome to Home</Text>
      <Text style={styles.buttonText}>Press Me</Text>
    </View>
  );
};

export default Home;


-3
投票

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

    useEffect(() => {
    subscription = Appearance.addChangeListener(({ colorScheme }) => {
        if (colorScheme === 'light') {
            dispatch(setMode(false));
        } else {
            dispatch(setMode(true));
        }
    });
    return () => subscription && subscription.remove();
}, []);
© www.soinside.com 2019 - 2024. All rights reserved.