跳到主要内容
版本:7.x

主题

主题允许您更改 React Navigation 提供的各种组件的颜色和字体。您可以使用主题来

  • 自定义颜色和字体以匹配您的品牌
  • 根据一天中的时间或用户偏好提供浅色和深色主题

基本用法

要传递自定义主题,您可以将 theme 属性传递给导航容器。

import * as React from 'react';
import {
useNavigation,
createStaticNavigation,
DefaultTheme,
} from '@react-navigation/native';

const MyTheme = {
...DefaultTheme,
colors: {
...DefaultTheme.colors,
background: 'rgb(140, 201, 125)',
primary: 'rgb(255, 45, 85)',
},
};

const Navigation = createStaticNavigation(Drawer);

export default function App() {
return <Navigation theme={MyTheme} />;
}
Snack 上尝试

您可以动态更改主题属性,所有组件将自动更新以反映新主题。如果您没有提供 theme 属性,将使用默认主题。

属性

主题是一个 JS 对象,包含要使用的颜色列表。它包含以下属性

  • dark (boolean): 这是否是深色主题或浅色主题
  • colors (object): react navigation 组件使用的各种颜色
    • primary (string): 应用的主色,用于为各种元素着色。通常您会希望为此使用您的品牌颜色。
    • background (string): 各种背景的颜色,例如屏幕的背景颜色。
    • card (string): 类似卡片元素的背景颜色,例如标题、标签栏等。
    • text (string): 各种元素的文本颜色。
    • border (string): 边框的颜色,例如标题边框、标签栏边框等。
    • notification (string): 通知和徽章的颜色(例如底部标签中的徽章)。
  • fonts (object): react navigation 组件使用的各种字体
    • regular (object): 应用中使用的主要字体的样式对象。
    • medium (object): 主要字体的半粗体变体的样式对象。
    • bold (object): 主要字体的粗体变体的样式对象。
    • heavy (object): 主要字体的特粗体变体的样式对象。

字体的样式对象包含以下属性

  • fontFamily (string): 要使用的字体系列名称(或 Web 上的字体堆栈),例如 RobotoHelvetica Neue。默认使用系统字体。
  • fontWeight (string): 要使用的字体粗细。有效值包括 normalbold100200300400500600700800900

创建自定义主题时,您需要提供所有这些属性。

主题示例

const WEB_FONT_STACK =
'system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';

const MyTheme = {
dark: false,
colors: {
primary: 'rgb(255, 45, 85)',
background: 'rgb(242, 242, 242)',
card: 'rgb(255, 255, 255)',
text: 'rgb(28, 28, 30)',
border: 'rgb(199, 199, 204)',
notification: 'rgb(255, 69, 58)',
},
fonts: Platform.select({
web: {
regular: {
fontFamily: WEB_FONT_STACK,
fontWeight: '400',
},
medium: {
fontFamily: WEB_FONT_STACK,
fontWeight: '500',
},
bold: {
fontFamily: WEB_FONT_STACK,
fontWeight: '600',
},
heavy: {
fontFamily: WEB_FONT_STACK,
fontWeight: '700',
},
},
ios: {
regular: {
fontFamily: 'System',
fontWeight: '400',
},
medium: {
fontFamily: 'System',
fontWeight: '500',
},
bold: {
fontFamily: 'System',
fontWeight: '600',
},
heavy: {
fontFamily: 'System',
fontWeight: '700',
},
},
default: {
regular: {
fontFamily: 'sans-serif',
fontWeight: 'normal',
},
medium: {
fontFamily: 'sans-serif-medium',
fontWeight: 'normal',
},
bold: {
fontFamily: 'sans-serif',
fontWeight: '600',
},
heavy: {
fontFamily: 'sans-serif',
fontWeight: '700',
},
},
}),
};

提供主题将负责所有官方导航器的样式设置。React Navigation 还提供了几种工具来帮助您自定义这些导航器,并且导航器内的屏幕也可以使用主题。

内置主题

随着操作系统增加对浅色和深色模式的内置支持,支持深色模式不再是为了赶时髦,更多的是为了符合普通用户对应用应该如何工作的期望。为了以与操作系统默认设置合理一致的方式提供对浅色和深色模式的支持,这些主题内置于 React Navigation 中。

您可以像这样导入默认和深色主题

import { DefaultTheme, DarkTheme } from '@react-navigation/native';

保持与原生主题同步

如果您在应用中更改主题,原生 UI 元素(例如 Alert、ActionSheet 等)将不会反映新主题。您可以执行以下操作以保持原生主题同步

React.useEffect(() => {
const colorScheme = theme.dark ? 'dark' : 'light';

if (Platform.OS === 'web') {
document.documentElement.style.colorScheme = colorScheme;
} else {
Appearance.setColorScheme(colorScheme);
}
}, [theme.dark]);

或者,您可以使用 useColorScheme Hook 来获取当前原生配色方案并相应地更新主题。

使用操作系统偏好设置

在 iOS 13+ 和 Android 10+ 上,您可以使用 (useColorScheme Hook) 获取用户首选的配色方案('dark''light')。

import {
useNavigation,
createStaticNavigation,
DefaultTheme,
DarkTheme,
useTheme,
} from '@react-navigation/native';
import { View, Text, TouchableOpacity, useColorScheme } from 'react-native';

const Navigation = createStaticNavigation(Drawer);

export default function App() {
const scheme = useColorScheme();

return <Navigation theme={scheme === 'dark' ? DarkTheme : DefaultTheme} />;
}

Snack 上尝试

在您自己的组件中使用当前主题

要访问在导航容器内渲染的任何组件中的主题,您可以使用 useTheme Hook。它返回主题对象

import {
useNavigation,
createStaticNavigation,
DefaultTheme,
DarkTheme,
useTheme,
} from '@react-navigation/native';
import { View, Text, TouchableOpacity, useColorScheme } from 'react-native';

function MyButton() {
const { colors } = useTheme();

return (
<TouchableOpacity style={{ backgroundColor: colors.card }}>
<Text style={{ color: colors.text }}>Button!</Text>
</TouchableOpacity>
);
}
Snack 上尝试