我在向我的反应本机应用程序添加深色主题支持时遇到问题。
主题上下文.js
import React from 'react';
const themes = {
dark: {
backgroundColor: 'gray',
backgroundCard: '#25282c',
color: 'white'
},
light: {
backgroundColor: 'yellow',
backgroundCard: '#fff',
color: 'black'
}
}
const initialState = {
dark: false,
theme: themes.light,
toggle: () => {}
}
const ThemeContext = React.createContext(initialState)
function ThemeProvider({children}) {
const [dark, setDark] = React.useState(false) // Default theme is light
// Toggle between dark and light modes
const toggle = () => {
setDark(!dark)
}
// Filter the styles based on the theme selected
const theme = dark ? themes.dark : themes.light
return(
<ThemeContext.Provider value={{theme, dark, toggle}}>
{children}
</ThemeContext.Provider>
)
}
export {ThemeProvider, ThemeContext}
应用程序.js
import 'react-native-gesture-handler';
import React, { Component } from 'react';
import {LogBox, SafeAreaView, StyleSheet, ScrollView, Button, View, Text, Image, Alert, TouchableOpacity, TouchableHighlight} from 'react-native';
import { NavigationContainer } from '@react-navigation/native';
import { createStackNavigator } from '@react-navigation/stack';
import Home from './Home.js';
import Settings from './Settings.js';
import Icon from 'react-native-vector-icons/FontAwesome';
import { ThemeProvider } from './theme-context'
const Stack = createStackNavigator();
function LogoTitle() {
return (
<Image
style={{ width: 140, height: 50 }}
source={require('./images/title.png')}
/>
);
}
// ------------------App-----------------------------
class App extends Component {
render() {
return (
<ThemeProvider>
<NavigationContainer>
<Stack.Navigator
screenOptions={{
headerStyle: {
backgroundColor: '#f4f4f4',
},
headerTintColor: 'gray',
headerTitleStyle: {
fontWeight: 'bold',
},
}}
>
<Stack.Screen
name="Home"
component={Home}
options={({ navigation, route }) => ({
headerTitle: props => <LogoTitle {...props} />,
headerRight: () => (
<Icon.Button
name="cog"
backgroundColor="transparent"
size={25}
onPress={() => navigation.navigate('Settings')}
title="Settings"
color="gray"
/>
),
})}
/>
<Stack.Screen
name="Settings"
component={Settings}
/>
</Stack.Navigator>
</NavigationContainer>
</ThemeProvider>
);
}
}
export default App;
home.js
import 'react-native-gesture-handler';
import React, { Component, useContext } from 'react';
import {LogBox, SafeAreaView, StyleSheet, ScrollView, View} from 'react-native';
import { Card } from 'react-native-elements';
import CardOne from './Components/CardOne.js';
import CardTwo from './Components/CardTwo.js';
import CardThree from './Components/CardThree.js';
import CardFour from './Components/CardFour.js';
import { ThemeProvider } from './theme-context';
// ------------------App-----------------------------
class Home extends Component {
constructor(props) {
super(props);
// ...
}
}
render() {
return (
<ThemeProvider>
<View>
<SafeAreaView>
<ScrollView >
<CardOne/>
<CardTwo/>
<CardThree/>
<CardFour />
</ScrollView>
</SafeAreaView>
</View>
</ThemeProvider>
);
}
}
export default Home;
接下来我想在我的一个组件上使用 useContext
import React, { Component, useContext} from 'react';
import { Card } from 'react-native-elements';
import {StyleSheet, View, Text, Image, Alert, TouchableOpacity} from 'react-native';
import { ThemeContext } from 'ResCalc/theme-context';
const { dark, theme, toggle } = useContext(ThemeContext);
class CardOne extends Component {
constructor(props) {
super(props);
...
}
}
render() {
return (
<Card containerStyle={styles.card}>
<View>
<Switch
onChange={toggle} value = {dark} />
</View>
</Card>
);
}
}
const styles = StyleSheet.create({
card: {
backgroundColor: theme.backgroundColor,
borderColor: "#D1D1D6",
borderWidth: 2,
borderRadius: 5,
shadowOffset:{ width: 5, height: 5, },
shadowColor: '#D1D1D6', // #D1D1D6
shadowOpacity: 1.0,
shadowRadius: 2,
elevation: 3,
}
});
export default CardOne
我想我必须在基于类的变体中使用 useContext 钩子,但我只是不知道如何做到这一点。
希望有人能帮我解决这个问题:)
您可以将样式定义为函数,然后将主题注入其中。
const styles = (theme) => StyleSheet.create({
card: {
backgroundColor: theme.backgroundColor,
borderColor: "#D1D1D6",
borderWidth: 2,
borderRadius: 5,
shadowOffset:{ width: 5, height: 5, },
shadowColor: '#D1D1D6', // #D1D1D6
shadowOpacity: 1.0,
shadowRadius: 2,
elevation: 3,
}
});
在您的组件中:
class CardOne extends Component {
static contextType = ThemeContext;
render() {
// Pass theme context to styles functiion
return (
<Card containerStyle={styles(this.context.theme).card}>
<View>
<Switch
onChange={toggle} value = {dark} />
</View>
</Card>
);
}
background: COLORS.WHITE,
text: COLORS.TEXTCOLOR_DARK,`enter code here`
primary: COLORS.PRIMARY,
secondary: COLORS.SECONDARY,
inactive: COLORS.INACTIVE,
chatback: "#EEEEEE",
qbutton: COLORS.WHITE,
};
export const darkTheme = {
background: COLORS.BLACK,
text: COLORS.TEXTCOLOR_LIGHT,
primary: COLORS.PRIMARY,
secondary: COLORS.SECONDARY,
inactive: COLORS.INACTIVE,
chatback: "#232323",
qbutton: "#2c2c2c",
};
export const useTheme = () => {
const selectedTheme = useSelector((state) => state.userdata.themes); // Selected theme from Redux
const [deviceTheme, setDeviceTheme] = useState(Appearance.getColorScheme());
useEffect(() => {
const subscription = Appearance.addChangeListener(({ colorScheme }) => {
setDeviceTheme(colorScheme);
});
}, []);
if (selectedTheme === "light") {
return lightTheme;
} else if (selectedTheme === "dark") {
return darkTheme;
} else {
// Fall back to device theme if no user selection
return deviceTheme === "dark" ? darkTheme : lightTheme;
}
};