第一次响应未听更改事件的本地外观



我正在尝试一个设置,这样当我更改系统主题时,我的react原生应用程序主题也应该更改。我使用了react导航和react原生外观。应用程序启动时应用了正确的系统主题,但当我第一次使用应用程序时更改主题时,它不会。但当我第二次尝试更改系统主题时,它也会更改应用程序主题并正常工作。

这是我的代码:-

App.js

import React from 'react';
import {} from 'react-native';
import {AppearanceProvider} from 'react-native-appearance';
import Main from './main';
export default function App() {

return (
<AppearanceProvider>
<Main/>
</AppearanceProvider>
);
}

Main.js

import React, { useState,useEffect } from 'react';
import {} from 'react-native';
import {Appearance} from 'react-native-appearance';
import {DarkTheme,DefaultTheme,NavigationContainer} from '@react-navigation/native';
import Home from './home';
const myDarkTheme={
...DarkTheme,
colors:{
...DarkTheme.colors,    
text:"#fff",
statusBarColor:"#000"
}
};

const myLightTheme={
...DefaultTheme,
colors:{
...DefaultTheme.colors,
text:"#000",
statusBarColor:"rgb(242, 242, 242)"
}
};

export default function Main(){
const [theme,setTheme]=useState();
console.log(theme);

const onThemeChange=()=>{
const newColor=Appearance.getColorScheme();
setTheme(newColor);
}
useEffect(()=>{
onThemeChange()
const subscription=Appearance.addChangeListener(()=>{
onThemeChange()
})
return ()=>subscription.remove();
},[])
return(
<NavigationContainer theme={theme === 'light' ? myLightTheme : myDarkTheme}>
<Home/>
</NavigationContainer>
)
}

和Home.js

import React from 'react';
import { StyleSheet, Text, View,StatusBar } from 'react-native';
import {useTheme} from '@react-navigation/native';
export default function Home(){
const {colors}=useTheme();
return (
<View style={{...styles.container,backgroundColor:colors.background}}>
<Text style={{color:colors.text}}>Open up App.js to start working on your app!</Text>
<StatusBar barStyle={colors.statusBarColor==='#000' ? 'light-content':'dark-content'} backgroundColor={colors.background}/>
</View>
);
}
const styles = StyleSheet.create({
container: {
flex: 1,
alignItems: 'center',
justifyContent: 'center',
},
});

请帮助我,当我在应用程序启动后第一次更改系统主题时,主题也会第一次更改。

修改MainActivity.java

import android.content.res.Configuration; // <--- import
// copy these lines
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
getReactInstanceManager().onConfigurationChanged(this, newConfig);
}

根据文档Appearence.addChangeListener,提供了具有colorScheme的回调函数。您可以使用它直接更新状态,无需再次调用onThemeChange((函数。

useEffect(()=>{
onThemeChange();
const subscription = Appearance.addChangeListener(({ colorScheme }) => {
setTheme(colorScheme);
})
return () => subscription.remove();
},[])

有一个悬而未决的问题,

https://github.com/facebook/react-native/issues/28823

如果你使用的是react native,那么你可以在上面问题上有人提供的分支中合并来解决它。但我使用的是Expo。

值得一提的是,如果您使用的是基于铬的调试器,主题将始终为light。禁用调试或切换调试程序。

https://github.com/facebook/react-native/issues/28823#issuecomment-640671784

我遇到了同样的问题,钩子只返回"轻",没有无论我在模拟器中切换多少外观。

经过对代码的大量挖掘,发现了它的原因这样做是由于调试器!如果您使用的是基于Chrome的调试器(在浏览器中或使用独立的RN调试器(由于调试器没有,外观模块将始终返回灯光能够处理异步函数(或者类似的东西,它是几天前!(。

我不能说我理解它为什么会这样做的特质,但结果是我停止了使用Chrome调试器移动到flipper,效果很好!我现在可以在黑暗之间切换了和使用useColorTheme挂钩的灯光模式。

希望这能帮助其他人,这让我很头疼等一下!

对于类组件

import React from "react";
import {
SafeAreaView,
Text,
View,
Dimensions,
StyleSheet,
TouchableHighlight,
Image,
ImageBackground,
TextInput,
TouchableOpacity,
ScrollView,
KeyboardAvoidingView,
FlatList,
Appearance,
Animated,
} from "react-native";
constructor(props) {
super(props);
this.state = {
theme: false,
};
}
componentDidMount() {
Appearance.getColorScheme() == "dark"
? this.setState({ theme: true })
: this.setState({ theme: false })

}


componentDidUpdate() {
this.subscription=Appearance.addChangeListener((theme) => {
// console.log("theme", theme);
theme.colorScheme == "dark"
? this.setState({ theme: true })
: this.setState({ theme: false });
});
}
componentWillUnmount() {
this.subscription.remove();
}
render() {
return (
<View
style={[
{
padding: 1,
flex: 1,
},
{ backgroundColor: this.state.theme == true ? "#000" : "#fff" },
]}

>
)}

对于功能部件

const [theme, setTheme] = useState(false);
useEffect(() => {
themeCheck();
}, []);

const themeCheck = async () => {
const getScheme = await Appearance.getColorScheme();
getScheme == "dark" ? setTheme(true) : setTheme(false);
};
useEffect(() => {
const subscription = Appearance.addChangeListener((theme) => {
// console.log("theme", theme);
theme.colorScheme == "dark" ? setTheme(true) : setTheme(false);
});
return () => subscription.remove();
},[])
return (
<>
{/* <StatusBar barStyle="light-content" */}
<SafeAreaView
style={[
styles.containerview1,
{ backgroundColor:theme == true ? "#000" : "#fff" },
]}
></SafeAreaView></>)

最新更新