Expo React Native StatusBar 隐藏但仍显示空白

问题描述 投票:0回答:1

我很确定这是我在这里发布的第一个问题,所以我希望我能正确地做到这一点并提供所有相关信息。

背景:

这是一个双重的个人项目。我严格为我和我的合作伙伴构建这个应用程序,因此没有重大限制,并且我愿意接受所有建议/推荐。她和我都经常旅行并会说几种外语,但我们每天仍在学习更多内容,并希望有一个可以一起使用和分享的个性化应用程序,所以我开始创建这个应用程序来提高我们的沟通和语言发展技能。

这个项目也恰好是我学习和提高 React Native 和原生 Kotlin/Swift 开发技能的绝佳机会(我尝试过 JavaFx 一段时间,但我是一名全职前端 Web 开发人员,所以 React Native对于 UI 开发和用于本机/后端的 Kotlin/Swift 来说,这似乎是一种更自然的方法。

它本质上只是一个学习应用程序,结合了我喜欢的 Quizlet、Anki、Pimsleur 等功能,并结合了一些聊天功能等,但这超出了本期的范围。请参阅我的问题陈述了解主要问题。

问题陈述:

我遇到的问题是,屏幕顶部的状态栏在将其设置为隐藏后仍然留有空白区域。尽管我已经尝试和研究了一切,但这个问题仍然存在。

目标:

我希望在隐藏 StatusBar 时显示我想要的背景颜色,或者根据它所在的活动/屏幕显示 ImageBackground。即屏幕顶部没有空白或凹口。

我已经尝试过:

  • 我已经尝试将
    backgroundColor
    设置为透明并将
    translucent
    属性设置为 true。
  • 在 app.json 中,我尝试将其配置为使用
    dark
    作为 userInterfaceStyle 属性。
  • 我尝试在整个应用程序中使用
    react-native-safe-area-context
    包及其
    SafeAreaProvider
    ,并在组件本身周围使用
    SafeAreaView
    (我知道常规 SafeAreaView 仅适用于 iOS,我特别需要这个用于 Android,我只是觉得也许这个上下文包值得一试)。
  • backgroundColor
    设置为黑色
  • style
    设置为深色,并将
    barStyle
    设置为深色内容
  • 我尝试过使用
    expo-status-bar
    react-native
    StatusBar(奇怪的是,即使我使用 expo,我对 expo-status-bar 也遇到了更多样式问题)

我已经没有办法尝试了。以上在实现它时都没有做任何事情。一旦我隐藏状态栏,顶部总是有空白,这很烦人。

代码:

应用程序.json

{
  "expo": {
    "name": "...",
    "slug": "...",
    "version": "1.0.0",
    "orientation": "portrait",
    "icon": "./assets/icon.png",
    "userInterfaceStyle": "dark",
    "splash": {
      "image": "./assets/....gif",
      "resizeMode": "contain",
      "backgroundColor": "#000000"
    },
    "assetBundlePatterns": [
      "**/*"
    ],
    "ios": {
      "supportsTablet": true,
      "bundleIdentifier": "com...."
    },
    "android": {
      "package": "com....",
      "adaptiveIcon": {
        "foregroundImage": "./assets/....gif",
        "backgroundColor": "#000000"
      }
    },
    "androidStatusBar": {
      "barStyle": "dark-content",
      "backgroundColor": "#000000",
      "hidden": true,
      "translucent": true
    },
    "web": {
      "favicon": "./assets/favicon.png"
    }
  }
}

抽认卡.js

import { useState, useEffect } from 'react';
import { View, Text, Pressable, StyleSheet, FlatList, Dimensions, ImageBackground, StatusBar } from 'react-native';
import { SafeAreaView } from 'react-native-safe-area-context';
import Logo from '../assets/....gif';

const DEVICE_WIDTH = Dimensions.get('window').width;

const SAMPLE = [
  {
    id: 0,
    name: "Русские карточки",
    description: "These are sample Russian flashcards.",
  },
  {
    id: 1,
    name: "Flashcards tiếng Việt",
    description: "These are sample Vietnamese flashcards.",
  },
  {
    id: 2,
    name: '中文抽認卡',
    description: 'These are sample Chinese flashcards.',
  },
  {
    id: 3,
    name: 'כרטיסי פלאש בעברית',
    description: 'These are sample Hebrew flashcards.',
  },
  {
    id: 4,
    name: 'Data structures',
    description: 'These are sample data structure flashcards.',
  },
  {
    id: 5,
    name: 'Countries',
    description: 'These are sample culture flashcards from countries around the world.',
  },
  {
    id: 6,
    name: 'Cultures',
    description: 'These are sample cultural tradition flashcards.',
  },
  {
    id: 7,
    name: 'Exercises',
    description: 'These are sample flashcards about healthy exercises.',
  },
  {
    id: 8,
    name: 'Final',
    description: 'This is the final collection just being used to see if it will make it scrollable.',
  }
];

export default function Flashcards({ navigation }) {
  const [collections, setCollections] = useState([]);
  const [selectedCollection, setSelectedCollection] = useState(null);

  useEffect(() => {
    setCollections(SAMPLE)
  }, [])

  const Item = ({ name, onPress, description }) => (
    <Pressable onPress={onPress} style={styles.item}>
      <Text style={styles.itemTitle}>{name}</Text>
      <Text style={styles.itemDescription}>{description}</Text>
    </Pressable>
  );

  const handleClick = (item) => {
    setSelectedCollection(item.id);
    navigation.navigate('StudyMode', {
      name: item.name,
    });
  };

  return (
    <SafeAreaView style={styles.container}>
      <StatusBar
        hidden
        backgroundColor="black"
        // translucent
        style="dark"
        barStyle="dark-content"
      />
      <ImageBackground
        source={Logo}
        style={styles.image}
        resizeMode="cover"
      >
        <View style={styles.titleContainer}>
          <Text style={styles.title}>Flashcards</Text>
        </View>
        <View style={styles.collectionsContainer}>
          <FlatList
            data={SAMPLE}
            style={styles.flatlist}
            renderItem={({ item }) => {
              return <Item onPress={() => handleClick(item)} name={item.name} description={item.description} />
            }}
            keyExtractor={item => item.id}
          />
        </View>
      </ImageBackground>
    </SafeAreaView>
  )
}

const styles = StyleSheet.create({
  container: {
    flex: 1,
    flexDirection: 'column',
    marginTop: StatusBar.currentHeight + 10 || 10,
    backgroundColor: '#000000',
    alignItems: 'center',
    justifyContent: 'center',
    paddingBottom: 60,
  },
  image: {
    flex: 1,
    justifyContent: 'center',
    contentFit: 'cover',
  },
  titleContainer: {
    borderBottomWidth: 6,
    borderColor: 'red',
    borderRadius: 12,
    backgroundColor: 'black',
    justifyContent: 'center',
    alignItems: 'center',
    marginLeft: 12,
    marginRight: 12,
    marginTop: 14,
    marginBottom: 10,
  },
  title: {
    color: 'white',
    fontFamily: 'Agright',
    fontSize: 32,
  },
  collectionsContainer: {
    borderWidth: 6,
    borderColor: 'red',
    borderRadius: 12,
    backgroundColor: 'black',
    width: DEVICE_WIDTH - 10,
  },
  flatlist: {
    flexGrow: 0,
    height: '100%',
  },
  item: {
    borderRadius: 12,
    borderWidth: 2,
    borderColor: 'red',
    width: '99%',
    alignItems: 'center',
    marginLeft: 2,
    marginRight: 2,
    marginTop: 6,
    marginBottom: 6,
    paddingVertical: 6,
    backgroundColor: '#000000',
  },
  itemTitle: {
    fontFamily: 'Agright',
    fontSize: 26,
    color: 'white',
  },
  itemDescription: {
    fontFamily: 'Agright',
    fontSize: 13,
    color: 'white',
  }
});

应用程序.js

import { useState, useEffect, useContext } from 'react';
import { NavigationContainer } from '@react-navigation/native';
import { createNativeStackNavigator } from '@react-navigation/native-stack';
import { SafeAreaProvider } from 'react-native-safe-area-context';
import * as SplashScreen from 'expo-splash-screen';
import * as Font from 'expo-font';
import { Platform, NativeModules } from 'react-native';
import { IntlProvider } from 'react-intl';
import en from './locales/en.json';
import he from './locales/he.json';
import ru from './locales/ru.json';
import uk from './locales/uk.json';
import vi from './locales/vi.json';
import zh from './locales/zh.json';

/**
 * Components
 */
import Login from './screens/Login';
import Home from './screens/Home';
import Flashcards from './screens/Flashcards';
import StudyMode from './screens/StudyMode';
import Texts from './screens/Texts';
import Translator from './screens/Translator';
import Dictionary from './screens/Dictionary';
import Chat from './screens/Chat';

/**
 * Hooks
 */
import useFonts from './hooks/useFonts';

/**
 * Context
 */
import { LocaleContextProvider, LocaleContext } from './context/LocaleContext';
import { DbContextProvider } from './database/DbContext';

/**
 * Messages (Localization)
 */
const messages = {
  'en': en,
  'en_US': en,
  'he': he,
  'ru': ru,
  'uk': uk,
  'vi': vi,
  'zh': zh,
};
const devicePlatform = Platform.OS;
const _deviceLocale = devicePlatform === 'android' ?
  NativeModules.I18nManager.localeIdentifier :
  NativeModules.SettingsManager.settings.AppleLocale ||
  NativeModules.SettingsManager.settings.AppleLanguages[0];
const deviceLocale = _deviceLocale.split(/[-_]/)[0];

SplashScreen.preventAutoHideAsync();

const Stack = createNativeStackNavigator();
const screenOptions = {
  headerStyle: {
    backgroundColor: '#000000',
  },
  headerTintColor: '#ffffff',
  headerTitleStyle: {
    fontFamily: 'Agright',
    textAlign: 'center'
  },
  headerTitleAlign: 'center',
};

export default function App() {
  const [appIsReady, setAppIsReady] = useState(false);
  const [isAuthNd, setIsAuthNd] = useState(false);
  const [isVisible, setIsVisible] = useState(false);
  const [fontsLoaded] = Font.useFonts({
    Agright: require('./assets/fonts/AgrightRegular-qZ5dr.otf'),
  })

  const { changeLanguage, currentLang } = useContext(LocaleContext);

  const loadFonts = async () => {
    try {
      await Font.loadAsync({
        Agright: require('./assets/fonts/AgrightRegular-qZ5dr.otf'),
        Fridays: require('./assets/fonts/Fridays-AWjM.ttf'),
        MyChemicalRomance: require('./assets/fonts/MyChemicalRomance-1X5Z.ttf'),
        Toxia: require('./assets/fonts/Toxia-OwOA.ttf'),
        Varukers: require('./assets/fonts/VarukersPersonalUse-K70Be.ttf'),
      });
    } catch (err) {
      console.error(err, err.stack);
    } finally {
      setAppIsReady(true);
    }
  };

  const loadHomeScreen = async () => {
    if (appIsReady) {
      await SplashScreen.hideAsync();
    }
  };

  useEffect(() => {
    if (fontsLoaded) {
      setAppIsReady(true);
    }
  }, [fontsLoaded]);

  useEffect(() => {
    if (appIsReady) {
      loadHomeScreen();
    }
  }, [appIsReady])

  if (!fontsLoaded) {
    return null;
  }

  return (
    <SafeAreaProvider>
      <DbContextProvider>
        <LocaleContextProvider>
          <IntlProvider messages={messages[currentLang]} locale={deviceLocale} defaultLocale="en">
            <NavigationContainer>
              <Stack.Navigator>
                {!isAuthNd
                  ? (
                    <Stack.Screen
                      name="Login"
                      component={Login}
                      options={{
                        ...screenOptions,
                        headerShown: false,
                      }}
                    />
                  )
                  : (
                    <Stack.Screen
                      name="Home"
                      component={Home}
                      options={{
                        ...screenOptions,
                        headerShown: false,
                      }}
                    />
                  )
                }
                <Stack.Screen
                  name="Home"
                  component={Home}
                  options={{
                    ...screenOptions,
                    headerShown: false,
                  }}
                />
                <Stack.Screen
                  name="Flashcards"
                  component={Flashcards}
                  options={{
                    ...subScreenOptions,
                    headerShown: false,
                  }}
                />
                <Stack.Screen
                  name="StudyMode"
                  component={StudyMode}
                  options={{
                    ...subScreenOptions,
                    headerShown: false,
                  }}
                />
                <Stack.Screen
                  name="Texts"
                  component={Texts}
                  options={{
                    ...subScreenOptions,
                    headerShown: false,
                  }}
                />
                <Stack.Screen
                  name="Translator"
                  component={Translator}
                  options={{
                    ...subScreenOptions,
                    headerShown: false,
                  }}
                />
                <Stack.Screen
                  name="Dictionary"
                  component={Dictionary}
                  options={{
                    ...screenOptions,
                    headerShown: false,
                  }}
                />
                <Stack.Screen
                  name="Chat"
                  component={Chat}
                  options={{
                    ...subScreenOptions,
                    headerShown: false,
                  }}
                />
              </Stack.Navigator>
            </NavigationContainer>
          </IntlProvider>
        </LocaleContextProvider>
      </DbContextProvider>
    </SafeAreaProvider>
  );
}

使用

  "dependencies": {
    "@react-navigation/native": "^6.1.6",
    "@react-navigation/native-stack": "^6.9.12",
    "@react-oauth/google": "^0.11.0",
    "axios": "^1.4.0",
    "expo": "~48.0.15",
    "expo-application": "~5.1.1",
    "expo-asset": "~8.9.1",
    "expo-auth-session": "~4.0.3",
    "expo-crypto": "~12.2.1",
    "expo-file-system": "~15.2.2",
    "expo-font": "^11.1.1",
    "expo-image": "~1.0.1",
    "expo-splash-screen": "~0.18.2",
    "expo-sqlite": "~11.1.1",
    "expo-web-browser": "~12.1.1",
    "isaac": "^0.0.5",
    "react": "18.2.0",
    "react-intl": "^6.4.4",
    "react-native": "0.71.8",
    "react-native-bcrypt": "^2.4.0",
    "react-native-crypto": "^2.2.0",
    "react-native-safe-area-context": "4.5.0",
    "uuid": "^9.0.0",
    "expo-system-ui": "~2.2.1"
  },
  "devDependencies": {
    "@babel/core": "^7.20.0"
  },

非常感谢您的帮助!

android react-native expo android-statusbar
1个回答
0
投票

您找到解决这个问题的方法了吗?我遇到了同样的问题。预先感谢。

© www.soinside.com 2019 - 2024. All rights reserved.