[英]React Native & Expo, how to control the splash screen?
I'm using the built in splash screen in expo that you add in app.json
for a simple test app.我正在使用您在
app.json
中添加的 expo 中内置的启动屏幕,用于一个简单的测试应用程序。 However I noticed that my start screen flashes in default mode 1 millisecond before showing the assets that I've added with AsyncStorage
.但是,我注意到在显示我使用
AsyncStorage
添加的资产之前,我的开始屏幕会以默认模式闪烁 1 毫秒。
I've tried using splash-screen package from expo but I found it a bit confusing.我尝试过使用 expo 中的闪屏包,但我发现它有点令人困惑。 Is there a fairly easy way to add in my
App.js
this logic :有没有一种相当简单的方法可以在我的
App.js
中添加这个逻辑:
Show a splash screen and when all assets are loaded, load this setup (with my contexts and screens), or just increase loading time of the build in splash screen from expo (because I assume it loads over the assets being fetched?).
显示一个启动画面,当所有资产都加载完毕时,加载这个设置(使用我的上下文和屏幕),或者只是增加来自 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>
);
};
You could use SplashScreen module from Expo.您可以使用 Expo 的SplashScreen模块。 Here is an overview of how you could use it:
以下是如何使用它的概述:
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>
);
}
There is also AppLoading component from Expo, but it seems to be deprecated. Expo也有AppLoading组件,但似乎已被弃用。 But it works, and here is an overview of how you would use it:
但它是有效的,这里是您如何使用它的概述:
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>
}
The section below is a special use case answering the above question:以下部分是回答上述问题的特殊用例:
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>
);
};
I had the same issue but in my case I have created an expo project with initial navigation screens.我遇到了同样的问题,但就我而言,我创建了一个带有初始导航屏幕的展览项目。 When you create a project with this setting, the App.tsx file will contain the hook useCachedResources.
当您使用此设置创建项目时,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>
);
}
}
When checking the hook, we can see that there is a code to keep the splash screen while loading the fonts.检查钩子时,我们可以看到有一个代码可以在加载字体时保持启动画面。 So we just add the timeout on the finally block before the SplashScreen.hideAsync().
所以我们只需在 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';
export default function useCachedResources() {
const [isLoadingComplete, setLoadingComplete] = useState(false);
useEffect(() => {
async function loadResourcesAndDataAsync() {
try {
SplashScreen.preventAutoHideAsync();
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;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.