React Native & Expo,如何控制启动画面?



我在expo中使用内置的启动屏幕,您在app.json中添加该屏幕用于一个简单的测试应用程序。然而,我注意到,在显示我使用AsyncStorage添加的资产之前,我的启动屏幕在默认模式下闪烁了1毫秒。

我试过使用expo的闪屏软件包但我觉得有点困惑。有没有一种相当简单的方法可以在我的App.js中添加这个逻辑:

显示一个启动屏幕,当加载所有资产时,加载此设置(使用我的上下文和屏幕(,或者只增加expo内置启动屏幕的加载时间(因为我认为它加载在要提取的资产上?(。

const App = () => {
const [selectedTheme, setSelectedTheme] = useState(themes.light)
const changeTheme = async () =>{
try {
const theme = await AsyncStorage.getItem("MyTheme")
if (theme === "dark"){
setSelectedTheme(themes.nightSky)} 
else if (theme === "light") {
setSelectedTheme(themes.arctic)
}
} catch (err) {alert(err)}
}

useEffect(()=> {
changeTheme()
},[])

return (
<ThemeContext.Provider value={{selectedTheme, changeTheme}}>
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown:false, presentation: 'modal'}}>
<Stack.Screen name="Home" component={home}/>
</Stack.Navigator>
</NavigationContainer>
</ThemeContext.Provider>
);
};

第一个解决方案

您可以使用世博会的SplashScreen模块。以下是如何使用它的概述:

expo install expo-splash-screen
import * as SplashScreen from "expo-splash-screen";
import React, { useCallback, useEffect, useState } from "react";
import { Text, View } from "react-native";
export default function App() {
const [appIsReady, setAppIsReady] = useState(false);
useEffect(() => {
async function prepare() {
// Keep the splash screen visible
await SplashScreen.preventAutoHideAsync();
// Do what you need before the splash screen gets hidden
console.log("I'm a task that gets executed before splash screen disappears");
// Then tell the application to render
setAppIsReady(true);
}
prepare();
}, []);
const onLayoutRootView = useCallback(async () => {
if (appIsReady) {
// Hide the splash screen
await SplashScreen.hideAsync();
}
}, [appIsReady]);
if (!appIsReady) {
return null;
}
return (
<View onLayout={onLayoutRootView} style={{ flex: 1, justifyContent: "center", alignItems: "center" }}><Text>Hello Word!</Text> </View>
);
}

第二个解决方案

还有来自Expo的AppLoading组件,但它似乎被弃用了。但它是有效的,下面是如何使用它的概述:

expo install expo-app-loading
import AppLoading from "expo-app-loading";
import {View, Text} from "react-native"

export default function App() {
const [isChecking, setIsChecking] = useState(true);
const  asyncDoThings = async ()=>{
// You do here all the fetching and checking process
}
if (isChecking) {
return (
<AppLoading
startAsync={() => asyncDoThings()}
onFinish={() => setIsChecking(false)}
onError={console.warn}
/>
);
}
return <View style={{ flex: 1, justifyContent: "center", alignItems: "center" }}><Text>Hello Word!</Text></View>

}

附加一个

以下部分是使用AppLoading:回答上述问题的特殊用例

import AppLoading from "expo-app-loading";
import {View} from "react-native"
const App = () => {
const [selectedTheme, setSelectedTheme] = useState(themes.light)
const [isChecking, setIsChecking] = useState(true);
const changeTheme = async () =>{
try {
const theme = await AsyncStorage.getItem("MyTheme")
if (theme === "dark"){
setSelectedTheme(themes.nightSky)} 
else if (theme === "light") {
setSelectedTheme(themes.arctic)
}
} catch (err) {alert(err)}
}

if (isChecking) {
return (
<AppLoading
startAsync={() =>   changeTheme()}
onFinish={() => setIsChecking(false)}
onError={console.warn}
/>
);
}

return (
<ThemeContext.Provider value={{selectedTheme, changeTheme}}>
<NavigationContainer>
<Stack.Navigator screenOptions={{headerShown:false, presentation: 'modal'}}>
<Stack.Screen name="Home" component={home}/>
</Stack.Navigator>
</NavigationContainer>
</ThemeContext.Provider>
);
};

我遇到了同样的问题,但在我的案例中,我创建了一个带有初始导航屏幕的expo项目。使用此设置创建项目时,App.tsx文件将包含钩子useCachedResources。

import { StatusBar } from 'expo-status-bar';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import useCachedResources from './src/hooks/useCachedResources';
import Navigation from './src/navigation';

export default function App() {
const isLoadingComplete = useCachedResources();
if (!isLoadingComplete) {
return null;
} else {
return (
<SafeAreaProvider>
<Navigation />
<StatusBar />
</SafeAreaProvider>
);
}
}

当检查钩子时,我们可以看到有一个代码可以在加载字体时保持启动屏幕。因此,我们只需在SplashScreen.hideAsync((.之前的finally块上添加超时

import { FontAwesome } from '@expo/vector-icons';
import * as Font from 'expo-font';
import * as SplashScreen from 'expo-splash-screen';
import { useEffect, useState } from 'react';
SplashScreen.preventAutoHideAsync();
export default function useCachedResources() {
const [isLoadingComplete, setLoadingComplete] = useState(false);
useEffect(() => {
async function loadResourcesAndDataAsync() {
try {
await Font.loadAsync({
...FontAwesome.font,
'space-mono': require('../assets/fonts/SpaceMono-Regular.ttf'),
});
} catch (e) {
console.warn(e);
} finally {
await new Promise(resolve => setTimeout(resolve, 2000));
setLoadingComplete(true);
SplashScreen.hideAsync();
}
}
loadResourcesAndDataAsync();
}, []);
return isLoadingComplete;
}

最新更新