You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在MUI中自定义暗黑模式调色板并实现全局切换开关?

Material UI暗黑模式定制与全局主题切换实现

一、自定义暗黑模式调色板

要让暗黑模式覆盖背景、按钮、文本等元素,需基于Material UI的createTheme方法,根据mode(light/dark)生成对应调色板,替换原有静态配置:

修改后的theme.palette.js

import { createTheme } from '@mui/material/styles';
import { amber, grey, green, indigo, red, common, blue } from '@mui/material/colors';

// 基础颜色定义
const baseColors = {
  white: common.white,
  primary: indigo[900],
  tertiary: blue[500],
  secondary: green[500],
  positive: green[500],
  medium: amber[700],
  negative: red[500],
  geometry: '#3bb2d0',
};

// 根据模式生成调色板
const getPalette = (mode) => ({
  mode,
  // 通用颜色
  colors: {
    ...baseColors,
    dark: mode === 'light' ? grey[800] : grey[200],
    neutral: mode === 'light' ? grey[500] : grey[400],
  },
  // 背景色:浅色用grey[50],深色用grey[900]
  background: {
    default: mode === 'light' ? grey[50] : grey[900],
    paper: mode === 'light' ? common.white : grey[800],
  },
  primary: {
    main: baseColors.primary,
    contrastText: common.white,
  },
  secondary: {
    main: baseColors.secondary,
    contrastText: common.white,
  },
  tertiary: {
    main: baseColors.tertiary,
  },
  // 文本颜色:自动适配模式
  text: {
    primary: mode === 'light' ? grey[900] : common.white,
    secondary: mode === 'light' ? grey[600] : grey[300],
  },
});

// 导出生成主题的函数
export default function generateTheme(mode = 'light') {
  return createTheme({
    palette: getPalette(mode),
    // 可添加typography、components等其他主题配置
  });
}

二、实现全局主题状态切换

1. 根组件管理主题状态

修改index.js,加入主题模式状态管理(示例用React useState,也可存入Redux):

import 'typeface-roboto';
import React, { useState, useEffect } from 'react';
import { createRoot } from 'react-dom/client';
import { BrowserRouter } from 'react-router-dom';
import { Provider } from 'react-redux';
import {
  CssBaseline,
  ThemeProvider,
  StyledEngineProvider,
} from '@mui/material';
import store from './store';
import { LocalizationProvider } from './common/components/LocalizationProvider';
import ErrorHandler from './common/components/ErrorHandler';
import generateTheme from './common/theme.palette'; // 导入主题生成函数
import Navigation from './Navigation';
import preloadImages from './map/core/preloadImages';
import * as serviceWorkerRegistration from './serviceWorkerRegistration';
import NativeInterface from './common/components/NativeInterface';
import ServerProvider from './ServerProvider';

preloadImages();

const App = () => {
  // 从localStorage读取保存的主题模式,默认浅色
  const [themeMode, setThemeMode] = useState(() => 
    localStorage.getItem('themeMode') || 'light'
  );
  const theme = generateTheme(themeMode);

  // 切换主题时保存到localStorage
  useEffect(() => {
    localStorage.setItem('themeMode', themeMode);
  }, [themeMode]);

  // 主题切换方法
  const toggleTheme = () => {
    setThemeMode(prev => prev === 'light' ? 'dark' : 'light');
  };

  return (
    <Provider store={store}>
      <LocalizationProvider>
        <StyledEngineProvider injectFirst>
          <ThemeProvider theme={theme}>
            <CssBaseline />
            {/* 将切换方法传递给Navigation,供设置页面调用 */}
            <ServerProvider>
              <BrowserRouter>
                <Navigation toggleTheme={toggleTheme} themeMode={themeMode} />
              </BrowserRouter>
            </ServerProvider>
            <ErrorHandler />
            <NativeInterface />
          </ThemeProvider>
        </StyledEngineProvider>
      </LocalizationProvider>
    </Provider>
  );
};

const root = createRoot(document.getElementById('root'));
root.render(<App />);

serviceWorkerRegistration.register();

2. 设置页面添加Switch组件

在设置页面组件中,引入Material UI组件实现切换开关:

import React from 'react';
import { Switch, FormControlLabel, Box } from '@mui/material';

const SettingsPage = ({ toggleTheme, themeMode }) => {
  return (
    <Box p={3}>
      <FormControlLabel
        control={
          <Switch
            checked={themeMode === 'dark'}
            onChange={toggleTheme}
            color="primary"
          />
        }
        label="暗黑模式"
      />
    </Box>
  );
};

export default SettingsPage;

三、关键说明

  • CssBaseline会自动根据主题模式设置全局背景色、文本色等基础样式,确保页面整体适配。
  • 将主题模式保存到localStorage可实现刷新页面后保留用户偏好。
  • 自定义的colors对象可通过theme.palette.colors在组件中访问,用于自定义样式。

内容的提问来源于stack exchange,提问作者cosmic

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 06:30:36