# Expo Documentation Expo is an open-source React Native framework for apps that run natively on Android, iOS, and the web. Expo brings together the best of mobile and the web and enables many important features for building and scaling an app such as live updates, instantly sharing your app, and web support. The company behind Expo also offers Expo Application Services (EAS), which are deeply integrated cloud services for Expo and React Native apps. # 开始使用 ## 介绍 开始使用 Expo 创建应用。 Expo 是一个使开发 Android 和 iOS 应用更容易的框架。我们的框架提供基于文件的路由、标准的原生模块库等等。Expo 是开源的,在 [GitHub](https://github.com/expo/expo) 和 [Discord](https://chat.expo.dev) 上有一个活跃的社区。 ¥Expo is a framework that makes developing Android and iOS apps easier. Our framework provides file-based routing, a standard library of native modules, and much more. Expo is open source with an active community on [GitHub](https://github.com/expo/expo) and [Discord](https://chat.expo.dev). 我们还制作了 [Expo 应用服务(EAS)](https://expo.dev/eas),这是一组在开发过程的每个步骤中补充 Expo 框架的服务。 ¥We also make [Expo Application Services (EAS)](https://expo.dev/eas), a set of services that complement the Expo framework in each step of the development process. 要开始使用,请访问: ¥To get started visit: ## 创建项目 了解如何创建新的 Expo 项目。 系统要求: ¥System requirements: * [Node.js (LTS)](https://nodejs.cn/)。 * 支持 macOS、Windows(Powershell 和 [WSL 2](https://expo.fyi/wsl))和 Linux。 ¥macOS, Windows (Powershell and [WSL 2](https://expo.fyi/wsl)), and Linux are supported. 我们建议从 `create-expo-app` 创建的默认项目开始。默认项目包含示例代码以帮助你入门。 ¥We recommend starting with the default project created by `create-expo-app`. The default project includes example code to help you get started. 要创建新项目,请运行以下命令: ¥To create a new project, run the following command: ```sh $ npx create-expo-app@latest ``` > 你可以通过添加 [`--template` 选项](/more/create-expo/#--template) 来选择不同的模板。 > > ¥You can choose a different template by adding the [`--template` option](/more/create-expo/#--template). ## 下一步 ¥Next step 你有一个项目。现在是时候设置你的开发环境,以便你可以开始开发了。 ¥You have a project. Now it's time to set up your development environment so that you can start developing. ## 设置你的环境 了解如何设置开发环境以开始使用 Expo 进行构建。 让我们设置一个本地开发环境以在 Android 和 iOS 上运行你的项目。 ¥Let's set up a local development environment for running your project on Android and iOS. ## 你想在哪里开发? ¥Where would you like to develop? 我们建议使用真实设备进行开发,因为你将能够准确地看到用户将看到的内容。 ¥We recommend using a real device to develop, since you'll get to see exactly what your users will see. ## 你想如何开发? ¥How would you like to develop? Expo Go 是一个用于快速试用 Expo 的沙盒。开发版本是你自己的应用的版本,其中包括 Expo 的开发者工具。 ¥Expo Go is a sandbox for trying out Expo quickly. A development build is a build of your own app that includes Expo's developer tools. *** # Android Emulator Setup ## Set up an emulator Step 1: On the Android Studio main screen, click **More Actions**, then **Virtual Device Manager** in the dropdown. Step 2: Click the **Create device** button. Step 3: Under **Select Hardware**, choose the type of hardware you'd like to emulate. We recommend testing against a variety of devices, but if you're unsure where to start, the newest device in the Pixel line could be a good choice. Step 4: Select an OS version to load on the emulator (probably one of the system images in the **Recommended** tab), and download the image. Step 5: Change any other settings you'd like, and press **Finish** to create the emulator. You can now run this emulator anytime by pressing the Play button in the AVD Manager window. # Android Studio Environment Setup ## Install Watchman and JDK #### Prerequisites Use a package manager such as [Homebrew](https://brew.sh/) to install the following dependency. #### Install dependencies Step 1: [Install Watchman](https://facebook.github.io/watchman/docs/install#macos) using a tool such as Homebrew: ```sh $ brew install watchman ``` Step 2: Install OpenJDK distribution called Azul Zulu using Homebrew. This distribution offers JDKs for both Apple Silicon and Intel Macs. Run the following commands in a terminal: ```sh $ brew install --cask zulu@17 ``` After you install the JDK, add the `JAVA_HOME` environment variable in **~/.bash_profile** (or **~/.zshrc** if you use Zsh): ```bash export JAVA_HOME=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` #### Prerequisites Use a package manager such as [Chocolatey](https://chocolatey.org/) to install the following dependencies. #### Install dependencies Install [Java SE Development Kit (JDK)](https://openjdk.org/): ```sh $ choco install -y microsoft-openjdk17 ``` For Linux: #### Install dependencies Step 1: Follow [instructions from the Watchman documentation](https://facebook.github.io/watchman/docs/install#linux) to compile and install it from the source. Step 2: Install [Java SE Development Kit (JDK)](https://openjdk.org/): You can download and install [OpenJDK@17](http://openjdk.java.net/) from [AdoptOpenJDK](https://adoptopenjdk.net/) or your system packager. # Android Studio Setup ## Set up Android Studio For macOS: Step 1: Download and install [Android Studio](https://developer.android.com/studio). Step 2: Open the **Android Studio** app, click **More Actions** and select **SDK Manager**. Step 3: Open Android Studio, go to **Settings** > **Languages & Frameworks** > **Android SDK**. From the **SDK Platforms** tab, select the latest Android version (API level). Then, click on the **SDK Tools** tab and make sure you have at least one version of the **Android SDK Build-Tools** and **Android Emulator** installed. Step 4: Copy or remember the path listed in the box that says **Android SDK Location**. Step 5: Click **Apply** and **OK** to install the Android SDK and related build tools. Step 6: If you are on macOS or Linux, add an [environment variable](https://developer.android.com/studio/command-line/variables#envar) pointing to the Android SDK location in **~/.bash_profile** (or **~/.zshrc** if you use Zsh). For example: `export ANDROID_HOME=/your/path/here`. Add the following lines to your **/.zprofile** or **~/.zshrc** (if you are using bash, then **~/.bash_profile** or **~/.bashrc**) config file: ```sh $ export ANDROID_HOME=$HOME/Library/Android/sdk $ export PATH=$PATH:$ANDROID_HOME/emulator $ export PATH=$PATH:$ANDROID_HOME/platform-tools ``` Step 7: Reload the path environment variables in your current shell: ```sh $ source $HOME/.zshrc $ source $HOME/.bashrc ``` Step 8: Finally, make sure that you can run `adb` from your terminal. Note: Troubleshooting: Android Studio not recognizing JDK --- If Android Studio doesn't recognize your homebrew installed JDK, you can create a Gradle configuration file to explicitly set the Java path: 1. Create a Gradle properties file in your home directory: ```sh $ touch ~/.gradle/gradle.properties ``` 2. Add the following line to the **gradle.properties** file, replacing the path with your actual Java installation path: ```bash gradle.properties java.home=/Library/Java/JavaVirtualMachines/zulu-17.jdk/Contents/Home ``` 3. If you have an existing `.gradle` folder in your project directory, delete it and reopen your project in Android Studio: ```sh $ rm -rf .gradle ``` This should resolve issues with Android Studio not detecting your JDK installation. --- For Windows: Step 1: Download [Android Studio](https://developer.android.com/studio). Step 2: Open **Android Studio Setup**. Under **Select components to install**, select Android Studio and Android Virtual Device. Then, click **Next**. Step 3: In the Android Studio Setup Wizard, under **Install Type**, select **Standard** and click **Next**. Step 4: The Android Studio Setup Wizard will ask you to verify the settings, such as the version of Android SDK, platform-tools, and so on. Click **Next** after you have verified. Step 5: In the next window, accept licenses for all available components. Step 6: After the tools installation is complete, configure the `ANDROID_HOME` environment variable. Go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** and click **New** to create a new `ANDROID_HOME` user variable. The value of this variable will point to the path to your Android SDK: Note: How to find installed SDK location? --- By default, the Android SDK is installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk ``` To find the location of the SDK in Android Studio manually, go to **Settings** > **Languages & Frameworks** > **Android SDK**. See the location next to **Android SDK Location**. --- Step 7: To verify that the new environment variable is loaded, open **PowerShell**, and copy and paste the following command: ```sh $ Get-ChildItem -Path Env: ``` The command will output all user environment variables. In this list, see if `ANDROID_HOME` has been added. Step 8: To add platform-tools to the Path, go to **Windows Control Panel** > **User Accounts** > **User Accounts** (again) > **Change my environment variables** > **Path** > **Edit** > **New** and add the path to the platform-tools to the list as shown below: Note: How to find installed platform-tools location --- By default, the platform-tools are installed at the following location: ```bash %LOCALAPPDATA%\Android\Sdk\platform-tools ``` --- Step 9: Finally, make sure that you can run `adb` from the PowerShell. For example, run the `adb --version` to see which version of the `adb` your system is running. # Xcode Setup Step 1: ### Install Xcode Open up the Mac App Store, search for [Xcode](https://apps.apple.com/us/app/xcode/id497799835), and click **Install** (or **Update** if you have it already). Step 2: ### Install Xcode Command Line Tools Open Xcode, choose **Settings...** from the Xcode menu (or press cmd ⌘ + ,). Go to the **Locations** and install the tools by selecting the most recent version in the **Command Line Tools** dropdown. Step 3: ### Install an iOS Simulator in Xcode To install an iOS Simulator, open **Xcode > Settings... > Components**, and under **Platform Support > iOS ...**, click **Get**. Step 4: ### Install Watchman [Watchman](https://facebook.github.io/watchman/docs/install#macos) is a tool for watching changes in the filesystem. Installing it will result in better performance. You can install it with: ```sh $ brew update $ brew install watchman ``` # Create a development build for a physical Android device with EAS ## Set up an Android device with a development build Step 1: ### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh $ npm install -g eas-cli ``` Step 2: ### Create an Expo account and login To build your app, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh $ eas login ``` Step 3: ### Configure your project Run the following command to create an EAS config in your project: ```sh $ eas build:configure ``` Step 4: ### Create a build Run the following command to create a development build: ```sh $ eas build --platform android --profile development ``` Step 5: ### Install the development build on your device After the build is complete, scan the QR code in your terminal or open the link on your device. Tap **Install** to download the build on your device, then tap **Open** to install it. # Create a development build for a physical Android device locally ## Set up an Android device with a development build ## Running your app on an Android device Step 1: ### Install expo-dev-client Run the following command in your project's root directory: ```sh $ npx expo install expo-dev-client ``` Step 2: ### Enable debugging over USB Most Android devices can only install and run apps downloaded from Google Play, by default. You will need to enable USB Debugging on your device to install your app during development. To enable USB debugging on your device, you will first need to enable the "Developer options" menu by going to **Settings** > **About phone** > **Software information** and then tapping the `Build number` row at the bottom seven times. You can then go back to **Settings** > **Developer options** to enable "USB debugging". Step 3: ### Plug in your device via USB Plug in your Android device via USB to your computer. Check that your device is properly connecting to ADB, the Android Debug Bridge, by running `adb devices` in your terminal. You should see your device listed with `device` listed next to it. For example: ```sh $ adb devices List of devices attached 8AHX0T32K device ``` Step 4: ### Run your app Run the following from your terminal: ```sh $ npx expo run:android ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. # Run on a physical Android device with Expo Go ## Set up an Android device with Expo Go Scan the QR code to download the app from the Google Play Store, or visit the Expo Go page on the [Google Play Store](https://play.google.com/store/apps/details?id=host.exp.exponent&referrer=docs).
# Create a development build for Android Emulator with EAS ## Set up an Android Emulator with a development build ## Create a development build Step 1: ### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh $ npm install -g eas-cli ``` Step 2: ### Create an Expo account and login To build your app, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh $ eas login ``` Step 3: ### Configure your project Run the following command to create an EAS config in your project: ```sh $ eas build:configure ``` Step 4: ### Create a build Run the following command to create a development build: ```sh $ eas build --platform android --profile development ``` Step 5: ### Install the development build on your emulator After the build is complete, the CLI will prompt you to automatically download and install it on the Android Emulator. When prompted, press Y to directly install it on the emulator. If you miss this prompt, you can download the build from the link provided in the terminal and drag and drop it onto the Android Emulator to install it. # Create a development build for Android Emulator locally ## Set up an Android Emulator with a development build ## Running your app on an Android Emulator Step 1: ### Install expo-dev-client Run the following command in your project's root directory: ```sh $ npx expo install expo-dev-client ``` Step 2: Run the following from your terminal: ```sh $ npx expo run:android ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. # Run on Android Emulator with Expo Go ## Set up an Android Emulator with Expo Go ## Install Expo Go When you start a development server with `npx expo start` on the [start developing](/get-started/start-developing) page, press a to open the Android Emulator. Expo CLI will install Expo Go automatically. # Create a development build for a physical iOS device with EAS ## Set up an iOS device with a development build Step 1: ### Enroll in the Apple Developer Program To install a development build on your iOS device, you will need an active subscription to the Apple Developer Program. Sign up for the [Apple Developer Program here](https://developer.apple.com/programs/). Step 2: ### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh $ npm install -g eas-cli ``` Step 3: ### Create an Expo account and login Next, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh $ eas login ``` Step 4: ### Configure your project Run the following command to create an EAS config in your project: ```sh $ eas build:configure ``` Step 5: ### Create an ad hoc provisioning profile To install a development build on your iOS device, you will need to create an ad hoc provisioning profile. Create one by running the following command in your terminal: ```sh $ eas device:create ``` Step 6: ### Create a development build Run the following command to create a development build: ```sh $ eas build --platform ios --profile development ``` Step 7: ### Install the development build on your device After the build is complete, scan the QR code in your terminal and tap **Open with iTunes** when it appears inside the Camera app. Alternatively, open the link displayed in the terminal on your device. After confirming the installation, the app will appear in your device's app library. Step 8: ### Turn on developer mode 1. Open **Settings** > **Privacy & Security**, scroll down to the **Developer Mode** list item and navigate into it. 2. Tap the switch to enable **Developer Mode**. After you do so, Settings presents an alert to warn you that Developer Mode reduces your device's security. To continue enabling **Developer Mode**, tap the alert's **Restart** button. 3. After the device restarts and you unlock it, the device shows an alert confirming that you want to enable Developer Mode. Tap **Turn On**, and enter your device passcode when prompted. > Alternatively, if you have Xcode installed on your Mac, you can use it to [enable iOS developer mode](/guides/ios-developer-mode/#connect-an-ios-device-with-a-mac). # Create a development build for a physical iOS device locally ## Set up an iOS device with a development build ## Set up Xcode and Watchman ## Configure your project Step 1: ### Install expo-dev-client Run the following command in your project's root directory: ```sh $ npx expo install expo-dev-client ``` Step 2: ### Plug in your device via USB and enable developer mode 1. Connect your iOS device to your Mac using a USB cable. Unlock the device and tap **Trust** if prompted. 2. Open Xcode. From the menu bar, select **Window** > **Devices and Simulators**. You will see a warning in Xcode to enable developer mode. 3. On your iOS device, open **Settings** > **Privacy & Security**, scroll down to the **Developer Mode** list item and navigate into it. 4. Tap the switch to enable **Developer Mode**. After you do so, Settings presents an alert to warn you that Developer Mode reduces your device's security. To continue enabling **Developer Mode**, tap the alert's **Restart** button. 5. After the device restarts and you unlock it, the device shows an alert confirming that you want to enable Developer Mode. Tap **Turn On**, and enter your device passcode when prompted. Step 3: ### Run the project on your device 1. Add the `ios.bundleIdentifier` in the **app.json** file in the root directory to a unique value so that Xcode generates the provisioning profile for the app signing step. 2. Run the following command in your project's root directory and select your plugged in device from the list: ```sh $ npx expo run:ios --device ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. # Run on a physical iOS device with Expo Go ## Set up an iOS device with Expo Go Scan the QR code to download the app from the App Store, or visit the Expo Go page on the [App Store](https://itunes.apple.com/app/apple-store/id982107779).
# Create a development build for iOS Simulator with EAS ## Set up an iOS Simulator with a development build ## Set up Xcode ## Create a development build Step 1: ### Install EAS CLI To build your app, you will need to install EAS CLI. You can do this by running the following command in your terminal: ```sh $ npm install -g eas-cli ``` Step 2: ### Create an Expo account and login Next, you will need to create an Expo account and login to the EAS CLI. 1. [Sign up](https://expo.dev/signup) for an Expo account. 2. Run the following command in your terminal to log in to the EAS CLI: ```sh $ eas login ``` Step 3: ### Configure your project Run the following command to create an EAS config in your project: ```sh $ eas build:configure ``` Step 4: ### Adjust your build profile To create a simulator-compatible development build, you'll need to update your build profile in **eas.json** to set the `ios.simulator` property to `true`: ```json eas.json { "build": { "development": { "developmentClient": true, "distribution": "internal", "ios": { "simulator": true } } } } ``` Step 6: ### Create a development build Run the following command to create a development build: ```sh $ eas build --platform ios --profile development ``` Step 7: ### Install the development build on your simulator After the build is complete, the CLI will prompt you to automatically download and install it on the iOS Simulator. When prompted, press Y to directly install it on the simulator. If you miss this prompt, you can download the build from the link provided in the terminal and drag and drop it onto the iOS Simulator to install it. # Create a development build for iOS Simulator locally ## Set up an iOS Simulator with a development build ## Set up Xcode and Watchman ## Running your app on an iOS Simulator Step 1: ### Install expo-dev-client Run the following command in your project's root directory: ```sh $ npx expo install expo-dev-client ``` Step 2: Run the following from your terminal: ```sh $ npx expo run:ios ``` > This command runs a development server after building your app. You can skip running `npx expo start` on the next page. # Run on iOS Simulator with Expo Go ## Set up an iOS Simulator with Expo Go ## Set up Xcode ## Install Expo Go When you start a development server with `npx expo start` on the [start developing](/get-started/start-developing) page, press i to open the iOS Simulator. Expo CLI will install Expo Go automatically. ## 下一步 ¥Next step 你有一个项目和一个开发环境。现在是时候开始开发了。 ¥You have a project and a development environment. Now it's time to start developing. ## 开始开发 对 Expo 项目进行第一次更改并在你的设备上实时查看。 Step 1: ## Start a development server To start the development server, run the following command: ```sh $ npx expo start ``` Step 2: ## Open the app on your device After running the command above, you will see a QR code in your terminal. Scan this QR code to open the app on your device. If you're using an Android Emulator or iOS Simulator, you can press a or i respectively to open the app. Note: Having problems? --- Make sure you are on the same Wi-Fi network on your computer and your device. If it still doesn't work, it may be due to the router configuration — this is common for public networks. You can work around this by choosing the **Tunnel** connection type when starting the development server, then scanning the QR code again. ```sh $ npx expo start --tunnel ``` > Using the **Tunnel** connection type will make the app reloads considerably slower than on **LAN** or **Local**, so it's best to avoid tunnel when possible. You may want to install and use an emulator or simulator to speed up development if **Tunnel** is required to access your machine from another device on your network. --- Step 3: ## Make your first change Open the **app/(tabs)/index.tsx** file in your code editor and make a change. ```diff diff --git a/app/(tabs)/index.tsx b/app/(tabs)/index.tsx index 45cfa0e..4d1b384 100644 --- a/app/(tabs)/index.tsx +++ b/app/(tabs)/index.tsx @@ -17,7 +17,7 @@ export default function HomeScreen() { } > - Welcome! + Hello World! ``` Note: Changes not showing up on your device? --- Expo Go is configured by default to automatically reload the app whenever a file is changed, but let's make sure to go over the steps to enable it in case somehow things aren't working. - Make sure you have the [development mode enabled in Expo CLI](/workflow/development-mode#development-mode). - Close the Expo app and reopen it. - Once the app is open again, shake your device to reveal the developer menu. If you are using an emulator, press Ctrl + M for Android or Cmd ⌘ + D for iOS. - If you see **Enable Fast Refresh**, press it. If you see **Disable Fast Refresh**, dismiss the developer menu. Now try making another change. --- --- ## File structure Below, you can get familiar with the default project's file structure: ## Features The default project template has the following features: ## 下一步 开发、审查和提交你的项目。 以下是继续构建应用的后续步骤: ¥Here are next steps to continue building your app: ### 重置你的项目 ¥Reset your project 你可以删除样板代码并重新开始新项目。运行以下命令重置你的项目: ¥You can remove the boilerplate code and start fresh with a new project. Run the following command to reset your project: ```sh $ npm run reset-project ``` 此命令将应用中的现有文件移动到 app-example,然后创建一个带有新 index.tsx 文件的新应用目录。 ¥This command will move the existing files in **app** to **app-example**, then create a new **app** directory with a new **index.tsx** file. ### 开发、审查和部署 ¥Develop, review, and deploy 通过阅读“开发”部分中的文档来了解如何开发。你将学习如何创建 [UI 元素](/develop/user-interface/splash-screen-and-app-icon/)、添加 [单元测试](/develop/unit-testing/)、包含 [原生模块](/config-plugins/introduction/) 等。 ¥Learn how to develop by reading the docs in the Develop section. You'll learn how to create [UI elements](/develop/user-interface/splash-screen-and-app-icon/), add [unit tests](/develop/unit-testing/), include [native modules](/config-plugins/introduction/), and more. 开发完应用后,你可以将其与 [review](/review/overview) 的队友共享。 ¥Once you've developed your app, you can share it with your teammates for [review](/review/overview). 最后,你可以将你的项目 [build](/deploy/build-project/) 和 [submit](/deploy/submit-to-app-stores/) 到应用商店。 ¥Finally, you can [build](/deploy/build-project/) and [submit](/deploy/submit-to-app-stores/) your project to the app stores. ### 分步指南 ¥Step-by-step guide 有关从头到尾使用 Expo 构建应用的指导性分步演练,请查看 [tutorial](/tutorial/introduction/)。 ¥For a guided, step-by-step walkthrough of building an app with Expo from start to finish, check out the [tutorial](/tutorial/introduction/). # 开发 ## 开发工具 Expo 工具和网站的概述,它们将帮助你完成项目构建过程的各个方面。 当你使用 Expo 创建新项目时,了解以下基本工具和网站可以帮助你完成应用开发之旅。此页面概述了推荐工具列表。 ¥When you create a new project with Expo, learning about the following essential tools and websites can help you during your app development journey. This page provides an overview of a list of recommended tools. ## Expo CLI Expo CLI 是一种开发工具,当你创建新项目时会自动与 `expo` 包一起安装。你可以通过利用 `npx`(Node.js 包运行器)来使用它。 ¥Expo CLI is a development tool and is installed automatically with `expo` package when you create a new project. You can use it by leveraging `npx` (a Node.js package runner). 它旨在帮助你在应用开发阶段更快地行动。例如,你与 Expo CLI 的第一次交互是通过运行以下命令启动开发服务器:`npx expo start`。 ¥It is designed to help you move faster during the app development phase. For example, your first interaction with Expo CLI is starting the development server by running the command: `npx expo start`. 以下是你在开发应用时将使用 Expo CLI 的常用命令列表: ¥The following is a list of common commands that you will use with Expo CLI while developing your app: | 命令 | 描述 | | ------------------------------- | ----------------------------------------------------------------------------------------------------- | | `npx expo start` | 启动开发服务器(无论你使用的是开发版本还是 Expo Go)。 | | `npx expo prebuild` | 使用 [预建](/workflow/prebuild/) 生成原生 Android 和 iOS 目录。 | | `npx expo run:android` | 在本地编译原生 Android 应用。 | | `npx expo run:ios` | 在本地编译原生 iOS 应用。 | | `npx expo install package-name` | 用于通过向此命令添加 `--fix` 选项来安装新库或验证和更新项目中的特定库。 | | `npx expo lint` | [设置和配置](/guides/using-eslint/) ESLint。如果 ESLint 已配置,此命令将 [本地与全局 URL 参数](/guides/using-eslint/#usage)。 | 简而言之,Expo CLI 允许你开发、编译、启动应用等。有关你可以使用 CLI 执行的更多可用选项和操作,请参阅 [Expo CLI 参考](/more/expo-cli/)。 ¥In a nutshell, Expo CLI allows you to develop, compile, start your app, and more. See [Expo CLI reference](/more/expo-cli/) for more available options and actions you can perform with the CLI. ## EAS 命令行接口 ¥EAS CLI EAS CLI 用于登录你的 Expo 账户并使用不同的 EAS 服务(例如 Build、Update 或 Submit)编译你的应用。你还可以使用此工具来: ¥EAS CLI is used to log in to your Expo account and compile your app using different EAS services such as Build, Update, or Submit. You can also use this tool to: * 将你的应用发布到应用商店 ¥Publish your app to the app stores * 创建应用的开发、预览或生产版本 ¥Create a development, preview, or production build of your app * 创建无线 (OTA) 更新 ¥Create over-the-air (OTA) updates * 管理你的应用凭据 ¥Manage your app credentials * 为 iOS 设备创建临时配置文件 ¥Create an ad hoc provisioning profile for an iOS device 要使用 EAS CLI,你需要通过运行以下命令在本地计算机上全局安装它: ¥To use EAS CLI, you need to install it globally on your local machine by running the command: ```sh $ npm install -g eas-cli ``` 你可以在终端窗口中使用 `eas --help` 来了解有关可用命令的更多信息。有关完整参考,请参阅 [`eas-cli` npm 页面](https://www.npmjs.com/package/eas-cli)。 ¥You can use `eas --help` in your terminal window to learn more about the available commands. For a complete reference, see [`eas-cli` npm page](https://www.npmjs.com/package/eas-cli). ## Expo Doctor Expo Doctor 是一个命令行工具,用于诊断 Expo 项目中的问题。要使用它,请在项目的根目录中运行以下命令: ¥Expo Doctor is a command line tool used to diagnose issues in your Expo project. To use it, run the following command in your project's root directory: ```sh $ npx expo-doctor ``` 此命令执行检查并分析项目的代码库,以查找 [应用配置](/workflow/configuration/) 和 package.json 文件、依赖兼容性、配置文件和项目整体运行状况中的常见问题。检查完成后,Expo Doctor 会输出结果。 ¥This command performs checks and analyzes your project's codebase for common issues in [app config](/workflow/configuration/) and **package.json** files, dependency compatibility, configuration files, and the overall health of the project. Once the check is complete, Expo Doctor outputs the results. 如果 Expo Doctor 发现问题,它会提供问题描述以及如何修复或在哪里寻求帮助的建议。 ¥If Expo Doctor finds an issue, it provides a description of the problem along with advice on how to fix it or where to find help. 默认情况下,Expo Doctor 会根据 [React Native 目录](https://reactnative.directory/) 验证你项目的包,并在存在原生目录时检查应用配置属性是否正确同步。你可以在项目的 package.json 文件中配置这些检查。有关更多详细信息,请参阅 [`reactNativeDirectoryCheck`](/versions/latest/config/package-json/#reactnativedirectorycheck) 和 [`appConfigFieldsNotSyncedCheck`](/versions/latest/config/package-json/#appconfigfieldsnotsynced)。 ¥By default, Expo Doctor validates your project's packages against the [React Native directory](https://reactnative.directory/) and checks if app config properties are properly synced when native directories exist. You can configure these checks in your project's **package.json** file. See [`reactNativeDirectoryCheck`](/versions/latest/config/package-json/#reactnativedirectorycheck) and [`appConfigFieldsNotSyncedCheck`](/versions/latest/config/package-json/#appconfigfieldsnotsynced) for more details. 你还可以使用 `npx expo-doctor --help` 显示使用信息。 ¥You can also use `npx expo-doctor --help` to display usage information. ## Orbit Orbit 是一款 macOS 和 Windows 应用,可实现: ¥Orbit is a macOS and Windows app that enables: * 在物理设备和模拟器上安装并启动来自 EAS 的构建。 ¥Install and launch builds from EAS on physical devices and emulators. * 在 Android 模拟器或 iOS 模拟器上安装并启动来自 EAS 的更新。 ¥Install and launch updates from EAS on Android Emulators or iOS Simulators. * 在 Android 模拟器或 iOS 模拟器上启动零食项目。 ¥Launch snack projects on Android Emulators or iOS Simulators. * 使用本地文件安装和启动应用。Orbit 支持任何 Android .apk、iOS Simulator 兼容的 .app 或临时签名的应用。 ¥Use local files to install and launch apps. Orbit supports any Android **.apk**, iOS Simulator compatible **.app**, or ad hoc signed apps. * 查看 EAS 仪表板中的固定项目列表。 ¥See a list of pinned projects from your EAS dashboard. ### 安装 ¥Installation For macOS: 你可以使用 Homebrew for macOS 下载 Orbit,也可以直接从 [GitHub 发布](https://github.com/expo/orbit/releases) 下载。 ¥You can download Orbit with Homebrew for macOS, or directly from the [GitHub releases](https://github.com/expo/orbit/releases). ```sh $ brew install expo-orbit ``` 如果你希望 Orbit 在你登录时自动启动,请单击菜单栏中的 Orbit 图标,然后单击“设置”并选择“登录时启动”选项。 ¥If you want Orbit to start when you log in automatically, click on the Orbit icon in the menu bar, then **Settings** and select the **Launch on Login** option. For Windows: > 注意:Windows 版 Orbit 处于预览阶段,仅与 x64 和 x86 机器兼容。将来会添加对其他架构的兼容性。 > > ¥**Note**: Orbit for Windows is in preview and is only compatible with x64 and x86 machines. Compatibility for other architectures will be added in the future. 你可以直接从 [GitHub 发布](https://github.com/expo/orbit/releases) 下载适用于 Windows 的 Orbit。 ¥You can download Orbit for Windows directly from the [GitHub releases](https://github.com/expo/orbit/releases). > **info** Orbit 依赖于 macOS 和 Windows 上的 Android SDK,以及 macOS 上仅用于设备管理的 `xcrun`,这需要同时设置 [安卓工作室](/workflow/android-studio-emulator/) 和 [Xcode](/workflow/ios-simulator/)。 > > ¥Orbit relies on the Android SDK on both macOS and Windows and `xcrun` for device management only on macOS, which requires setting up both [Android Studio](/workflow/android-studio-emulator/) and [Xcode](/workflow/ios-simulator/). {/* ### Usage */} ## VS Code 的 Expo 工具 ¥Expo Tools for VS Code Expo Tools 是一个 VS Code 扩展,可在使用应用配置文件时改善你的开发体验。它为应用配置、EAS 配置、存储配置和 Expo Module 配置文件等文件提供自动补齐和智能感知等功能。 ¥Expo Tools is a VS Code extension to improve your development experience when working with app config files. It provides features such as autocomplete and intellisense for files such as app config, EAS config, store config and Expo Module config files. 你还可以使用它来调试你的应用,使用 VS Code 的内置调试器设置断点、检查变量、通过调试控制台执行代码等。有关如何使用此扩展进行调试,请参阅 [使用 VS Code 进行调试](/debugging/tools/#debugging-with-vs-code)。 ¥You can also use it to debug your app using VS Code's built-in debugger to set breakpoints, inspect variables, execute code through the debug console, and more. See [Debugging with VS Code](/debugging/tools/#debugging-with-vs-code) for how to use this extension for debugging. ## 使用测试原型小样和 Expo Go ¥Test prototypes with Snack and Expo Go ### Snack Snack 是一个浏览器内开发环境,其工作原理与 Expo Go 类似。这是共享代码片段和试验 React Native 的好方法,无需在计算机上下载任何工具。 ¥Snack is an in-browser development environment that works similarly to Expo Go. It's a great way to share code snippets and experiment with React Native without downloading any tools on your computer. 要使用它,请转到 [snack.expo.dev](https://snack.expo.dev/),在 App.js 中编辑 `` 组件,在右侧面板中选择一个平台(Android、iOS 或 Web)并实时查看更改。 ¥To use it, go to [snack.expo.dev](https://snack.expo.dev/), edit the `` component in **App.js**, choose a platform (Android, iOS, or web) in the right panel and see the changes live. ### Expo [Expo](https://expo.dev/go) 是一个免费的开源沙盒,用于学习和试验 React Native。它适用于 Android 和 iOS。 ¥[Expo Go](https://expo.dev/go) is a free open-source, sandbox for learning and experimenting with React Native. It works with Android and iOS. 有关如何使用它的更多信息: ¥For more information on how to use it: * 单击 [树摇动](/get-started/set-up-your-environment/?mode=expo-go) 转到“设置你的环境”指南 ¥Click [this link](/get-started/set-up-your-environment/?mode=expo-go) to go to Set up your environment guide * 在“你想在哪里开发?”下选择要开发的平台 ¥Select a platform to develop under **Where would you like to develop?** * 在“你想如何开发?”下选择 Expo Go ¥Select Expo Go under **How would you like to develop?** * 按照该指南中描述的说明操作 ¥Follow the instructions described in that guide > 注意:不建议构建生产应用并将其分发到应用商店。请改用 [开发构建](/get-started/set-up-your-environment/?mode=development-build)。 > > ¥**Note:** Not recommended for building and distributing production apps to the app stores. Instead, use [development builds](/get-started/set-up-your-environment/?mode=development-build). Note: What if I open a project with an unsupported SDK version? --- When running a project that was created for an unsupported SDK version in Expo Go, you'll see the following error: ```sh "Project is incompatible with this version of Expo Go" ``` To fix this, upgrading your project to a [supported SDK version](/versions/latest/#each-expo-sdk-version-depends-on-a-react-native-version) is recommended. If you want to learn how to do it, see [Upgrade the project to a new SDK Version](#how-do-i-upgrade-my-project-from). --- Note: How do I upgrade my project from an unsupported SDK version? --- See [Upgrading Expo SDK guide](/workflow/upgrading-expo-sdk-walkthrough) for instructions for upgrading to a specific SDK version. --- ## React Native 目录 ¥React Native directory 当你使用开发版本创建项目时,任何与 React Native 兼容的库都可以在 Expo 项目中使用。 ¥Any library that is compatible with React Native works in an Expo project when you use a development build to create your project. [reactnative.directory](https://reactnative.directory/) 是一个可搜索的 React Native 库数据库。如果你要查找的库未包含在 Expo SDK 中,请使用目录查找与你的项目兼容的库。 ¥[reactnative.directory](https://reactnative.directory/) is a searchable database for React Native libraries. If a library you are looking for is not included in Expo SDK, use the directory to find a compatible library for your project. ## 验证 了解如何在 Expo 项目中设置身份验证。 Expo 可用于登录 Android、iOS 和 Web 上的许多流行提供商。[`expo-auth-session`](/versions/latest/sdk/auth-session/) 包允许 [基于浏览器的身份验证](/versions/latest/sdk/auth-session/#how-web-browser-based-authentication-flows-work)(使用 OAuth 或 OpenID Connect)到你的 Android、iOS 和 Web 项目。你还可以使用 [开发构建](/develop/development-builds/create-a-build) 的第三方提供商的原生库来实现身份验证。 ¥Expo can be used to login to many popular providers on Android, iOS, and web. [`expo-auth-session`](/versions/latest/sdk/auth-session/) package allows [browser-based authentication](/versions/latest/sdk/auth-session/#how-web-browser-based-authentication-flows-work) (using OAuth or OpenID Connect) to your project for Android, iOS, and the web. You can also implement authentication using native libraries for third-party providers with [development builds](/develop/development-builds/create-a-build). ## 使用 Jest 进行单元测试 了解如何设置和配置 jest-expo 库以使用 Jest 为项目编写单元和快照测试。 [Jest](https://jest.nodejs.cn) 是最广泛使用的单元和快照 JavaScript 测试框架。在本指南中,你将学习如何在项目中设置 Jest、编写单元测试、编写快照测试,以及在将 Jest 与 React Native 结合使用时构建测试的最佳实践。 ¥[Jest](https://jest.nodejs.cn) is the most widely used unit and snapshot JavaScript testing framework. In this guide, you will learn how to set up Jest in your project, write a unit test, write a snapshot test, and best practices for structuring your tests when using Jest with React Native. 你还将使用 [`jest-expo`](https://github.com/expo/expo/tree/main/packages/jest-expo) 库,这是一个 Jest 预设,可模拟 Expo SDK 的原生部分并处理 Expo 项目所需的大部分配置。 ¥You will also use the [`jest-expo`](https://github.com/expo/expo/tree/main/packages/jest-expo) library, which is a Jest preset that mocks the native part of the Expo SDK and handles most of the configuration required for your Expo project. ## 安装和配置 ¥Installation and configuration 创建 Expo 项目后,请按照以下说明在你的项目中安装和配置 `jest-expo`: ¥After creating your Expo project, follow the instructions below to install and configure `jest-expo` in your project: Step 1: Install `jest-expo` and other required dev dependencies in your project. Run the following command from your project's root directory: For macOS/Linux: ```sh $ npx expo install jest-expo jest @types/jest --dev ``` For Windows: ```sh $ npx expo install jest-expo jest @types/jest "--" --dev ``` > **Note:** If your project is not using TypeScript, you can skip installing `@types/jest`. Step 2: Open **package.json**, add a script for running tests, and add the preset for using the base configuration from `jest-expo`: ```json package.json { "scripts": { }, "jest": { "preset": "jest-expo" } } ``` Step 3: In **package.json**, add `jest-expo` as a preset so that a base for Jest's configuration is set up: ```json package.json { "jest": { "preset": "jest-expo" } } ``` Note: Additional configuration for using --- You can transpile node modules your project uses by configuring [`transformIgnorePatterns`](https://jest.nodejs.cn/docs/configuration#transformignorepatterns-arraystring) in your **package.json**. This property takes a regex pattern as its value: For npm/Yarn: ```json package.json "jest": { "preset": "jest-expo", "transformIgnorePatterns": [ "node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg)" ] } ``` For pnpm: ```json package.json "jest": { "preset": "jest-expo", "transformIgnorePatterns": [ "node_modules/(?!(?:.pnpm/)?((jest-)?react-native|@react-native(-community)?|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@sentry/react-native|native-base|react-native-svg))" ] } ``` Jest has many configuration options, but the above configuration should cover most of your needs. However, you can always add to this pattern list. For more details, see [Configuring Jest](https://jest.nodejs.cn/docs/configuration). --- ## Install React Native Testing Library The [React Native Testing Library (`@testing-library/react-native`)](https://callstack.github.io/react-native-testing-library/) is a lightweight solution for testing React Native components. It provides utility functions and works with Jest. To install it, run the following command: For macOS/Linux: ```sh $ npx expo install @testing-library/react-native --dev ``` For Windows: ```sh $ npx expo install @testing-library/react-native "--" --dev ``` > **warning** **Deprecated:** `@testing-library/react-native` replaces the deprecated `react-test-renderer` because `react-test-renderer` does not support React 19 and above. Remove the deprecated library from your project if you are currently using it. See [React's documentation for more information](https://react.nodejs.cn/warnings/react-test-renderer). ## Unit test A unit test checks the smallest unit of code, usually a function. To write your first unit test, take a look at the following example: Step 1: Inside the **app** directory of your project, create a new file called **index.tsx**, and the following code to render a simple component: ```tsx index.tsx import { PropsWithChildren } from 'react'; import { StyleSheet, Text, View } from 'react-native'; export const CustomText = ({ children }: PropsWithChildren) => {children}; export default function HomeScreen() { return ( Welcome! ); } const styles = StyleSheet.create({ container: { flex: 1, backgroundColor: '#fff', alignItems: 'center', justifyContent: 'center', }, }); ``` Step 2: Create a **\_\_tests\_\_** directory at the root of your project's directory. If this directory already exists in your project, use that. Then, create a new file called **HomeScreen-test.tsx**. The `jest-expo` preset customizes the Jest configuration to also identify files with **-test.ts|tsx** extensions as tests. Add the following example code in **HomeScreen-test.tsx**: ```tsx HomeScreen-test.tsx import { render } from '@testing-library/react-native'; import HomeScreen, { CustomText } from '@/app/index'; describe('', () => { test('Text renders correctly on HomeScreen', () => { const { getByText } = render(); getByText('Welcome!'); }); }); ``` In the above example, the `getByText` query helps your tests find relevant element in your app's user interface and make assertion whether or not the certain element exists. The React Native Testing Library provides this query, and each [query variant](https://callstack.github.io/react-native-testing-library/docs/api/queries#query-variant) differs in its return type. For more examples and detailed API information, see the React Native Testing Library's [Queries API reference](https://callstack.github.io/react-native-testing-library/docs/api/queries). Step 3: Run the following command in a terminal window to execute the test: ```sh $ npm run test ``` You will see one test being passed. ## Structure your tests Organizing your test files is important to make them easier to maintain. A common pattern is creating a **\_\_tests\_\_** directory and putting all your tests inside. An example structure of tests next to the **components** directory is shown below: Alternatively, you can have multiple **\_\_tests\_\_** sub-directories for different areas of your project. For example, create a separate test directory for **components**, and so on: It's all about preferences, and it is up to you to decide how you want to organize your project directory. ## Snapshot test > **info** **Note:** For UI testing, we recommend end-to-end tests instead of snapshot unit tests. See the [E2E tests with Maestro](/eas/workflows/examples/e2e-tests/) guide. A [snapshot test](https://jest.nodejs.cn/docs/en/snapshot-testing) is used to make sure that UI stays consistent, especially when a project is working with global styles that are potentially shared across components. To add a snapshot test for ``, add the following code snippet in the `describe()` in **HomeScreen-test.tsx**: ```tsx HomeScreen-test.tsx describe('', () => { test('CustomText renders correctly', () => { const tree = render(Some text).toJSON(); expect(tree).toMatchSnapshot(); }); }); ``` Run `npm run test` command, and you will see a snapshot created inside **\_\_tests\_\_\\\_\_snapshots\_\_** directory, and two tests passed. ## Code coverage reports Code coverage reports can help you understand how much of your code is tested. To see the code coverage report in your project using the HTML format, in **package.json**, under `jest`, set the `collectCoverage` to true and use `collectCoverageFrom` to specify a list of files to ignore when collecting the coverage. ```json package.json "jest": { ... "collectCoverage": true, "collectCoverageFrom": [ "**/*.{ts,tsx,js,jsx}", "!**/coverage/**", "!**/node_modules/**", "!**/babel.config.js", "!**/expo-env.d.ts", "!**/.expo/**" ] } ``` Run `npm run test`. You will see a **coverage** directory created in your project. Find the **lcov-report/index.html** and open it in a browser to see the coverage report. > 通常,我们不建议将 index.html 文件上传到 git。在 .gitignore 文件中添加 `coverage/**/*` 以防止被跟踪。 ¥Usually, we don't recommend uploading **index.html** file to git. Add `coverage/**/*` in the **.gitignore** file to prevent it from being tracked. ## Jest 流程(可选) ¥Jest flows (optional) 你还可以使用不同的流程来运行测试。以下是你可以尝试的一些示例脚本: ¥You can also use different flows to run your tests. Below are a few example scripts that you can try: ```json package.json "scripts": { "test": "jest --watch --coverage=false --changedSince=origin/main", "testDebug": "jest -o --watch --coverage=false", "testFinal": "jest", "updateSnapshots": "jest -u --coverage=false" } ``` 有关更多信息,请参阅 Jest 文档中的 [CLI 选项](https://jest.nodejs.cn/docs/en/cli)。 ¥For more information, see [CLI Options](https://jest.nodejs.cn/docs/en/cli) in Jest documentation. ## 附加信息 ¥Additional information # 导航 ## 基于文件的路由 了解 Expo Router,它是一个基于文件的路由系统,以及如何在你的项目中使用它。 本指南提供了 Expo Router 和导航模式(堆栈和选项卡)的基本约定和指导。要继续,你可以在现有项目中 [使用默认模板创建项目](/get-started/create-a-project/) 或安装 [Expo Router 库手动](/router/installation/#manual-installation)。 ¥This guide provides basic conventions and guidance for Expo Router and navigation patterns (stack and tabs). To follow along, you can [create a project by using the default template](/get-started/create-a-project/) or install [Expo Router library manually](/router/installation/#manual-installation) in your existing project. ## 什么是 Expo Router? ¥What is Expo Router? Expo Router 是用于 React Native 和 Web 应用的路由框架。它允许你管理应用中屏幕之间的导航,并在多个平台(Android、iOS 和 Web)上使用相同的组件。它使用基于文件的方法来确定应用内的路由。它还提供原生导航并建立在 [React 导航](https://react-navigation.nodejs.cn/) 之上。 ¥Expo Router is a routing framework for React Native and web applications. It allows you to manage navigation between screens in your app and use the same components on multiple platforms (Android, iOS and web). It uses a file-based method to determine routes inside your app. It also provides native navigation and is built on top of [React Navigation](https://react-navigation.nodejs.cn/). ## app 目录 ¥app directory 该应用是一个特殊目录。你添加到此目录的任何文件都将成为原生应用内的路由,并在网络上反映该路由的相同 URL。 ¥The **app** is a special directory. Any file you add to this directory becomes a route inside the native app and reflects the same URL for that route on the web. ## 创建路由 ¥Create a route 在 app 目录中,通过添加包含 index.tsx 文件的文件或嵌套目录来创建路由。 ¥In the **app** directory, a route is created by adding a file or a nested directory that includes **index.tsx** file. 例如,要创建应用的初始路由,你可以使用以下代码将 index.tsx 添加到应用目录: ¥For example, to create an initial route of your app, you can add **index.tsx** to the **app** directory with the following code: ```tsx app/index.tsx|collapseHeight=280 import { View, Text, StyleSheet } from 'react-native'; export default function HomeScreen() { return ( Home ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` app/index.tsx 文件将与 `/` 路由匹配,创建此文件后,应用目录结构为: ¥The **app/index.tsx** file will match the `/` route and after creating this file the **app** directory structure is: ### 文件名约定 ¥File name conventions 名为 index 的文件与父目录匹配,并且不添加路径段。例如,如果你通过添加 app/settings/index.tsx 来扩展应用的文件结构,它将匹配 `/settings` 路由。 ¥Files named **index** match the parent directory and do not add a path segment. For example, if you expand the app's file structure by adding **app/settings/index.tsx**, it will match the `/settings` route. > 注意:通过将 React 组件导出为默认值来定义路由文件。该文件必须使用 `.js`、`.jsx`、`.ts` 或 `.tsx` 扩展名。 > > ¥**Note:** A route file is defined by exporting a React component as the default value. The file must use either `.js`, `.jsx`, `.ts`, or `.tsx` extension. ## \_layout 文件 ¥\_layout file 目录中的布局文件用于定义共享 UI 元素(例如标题、标签栏),以便它们在不同路由之间保持不变。 ¥Layout files in a directory are used to define shared UI elements such as headers, tab bars so that they persist between different routes. 每次你创建新项目时,默认情况下,应用目录将包含一个根布局文件(app/_layout)。 ¥Any time you create a new project, by default the **app** directory will contain a **root layout** file (**app/_layout**). ### 根布局 ¥Root layout 传统上,React Native 项目由单个根组件构成(定义为 App.js 或 index.js)。类似地,应用目录中的第一个布局文件(_layout.tsx)被视为单个根组件。 ¥Traditionally, React Native projects are structured with a single root component (defined as **App.js** or **index.js**). Similarly, the first layout file (**_layout.tsx**) inside the **app** directory is considered to be the single root component. 在多个路由之间,Expo Router 中的 Root 布局文件用于在多个路由之间共享 UI,例如注入全局提供程序、主题、样式、延迟启动画面渲染直到加载资源和字体,或定义应用的根导航结构。 ¥Between multiple routes, a Root layout file in Expo Router is used to share UI between multiple routes such as injecting global providers, themes, styles, delay splash screen rendering until assets and fonts are loaded, or defining your app's root navigation structure. 例如,以下代码导出一个名为 `RootLayout` 的默认 React 组件: ¥For example, the following code exports a default React component called `RootLayout`: ```tsx app/_layout.tsx export default function RootLayout() { return ( ) } ``` > **info** 使用 Expo Router,app/_layout.tsx 中定义的任何 React 提供程序都可以通过应用中的任何路由访问。要提高性能并减少渲染次数,请尝试将提供程序的范围缩小到仅需要它们的路由。 > > ¥With Expo Router, any React providers defined inside **app/_layout.tsx** are accessible by any route in your app. To improve performance and cause fewer renders, try to reduce the scope of your providers to only the routes that need them. ## 堆栈导航器 ¥Stack navigator 堆栈导航器是一种在应用中的不同路由之间导航的模式。它允许在屏幕之间转换并管理导航历史记录。它在概念上类似于 Web 浏览器处理导航状态的方式。 ¥A stack navigator is a pattern to navigate between different routes in an app. It allows transitioning between screens and managing the navigation history. It is conceptually similar to how a web browser handles the navigation state. 例如,如果你想添加新路由 `/details`,请创建 details.tsx 文件。这将允许应用用户从 `/` 路由导航到 `/details`: ¥For example, if you want to add a new route `/details`, create **details.tsx** file. This will allow the app user to navigate from the `/` route to `/details`: ```tsx app/details.tsx|collapseHeight=300 import { View, Text, StyleSheet } from 'react-native'; export default function DetailsScreen() { return ( Details ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` 创建此路由文件后,当前文件结构如下: ¥After creating this route file, the current file structure looks like: 要允许在两个路由(`/` 和 `/details`)之间导航,请更新 Root 布局文件并向其中添加 `Stack` 组件: ¥To allow navigation between two routes (`/` and `/details`), update the Root layout file and add a `Stack` component to it: ```tsx app/_layout.tsx|collapseHeight=440 import { Stack } from 'expo-router'; export default function RootLayout() { return ( ); } ``` 布局文件中的 `` 组件允许在堆栈中定义路由。 ¥`` component in the layout file allows defining routes in a stack. > 注意:上面示例中的 `screenOptions` 允许为堆栈内的所有路由配置选项。请参阅 [静态配置路由选项](/router/advanced/stack/#statically-configure-route-options) 了解更多信息。 > > ¥**Note:** The `screenOptions` in the above example allows configuring options for all the routes inside a stack. See [Statically configure route options](/router/advanced/stack/#statically-configure-route-options) for more information. ## 在路由之间导航 ¥Navigating between routes Expo Router 使用名为 `Link` 的内置组件在应用中的路由之间移动。这在概念上类似于 Web 使用 `` 标签和 `href` 属性的方式。 ¥Expo Router uses a built-in component called `Link` to move between routes in an app. This is conceptually similar to how web works with the `` tag and the `href` attribute. 你可以通过从 Expo Router 库导入它,然后将 `href` 属性与要导航的路由一起传递作为属性的值来使用它。例如,要从 `/` 导航到 `/details`,请在 index.tsx 文件中添加 `Link` 组件: ¥You can use it by importing it from Expo Router library and then passing the `href` prop with the route to navigate as the value of the prop. For example, to navigate from `/` to `/details`, add a `Link` component in the **index.tsx** file: ```tsx app/index.tsx|collapseHeight=300 import { Link } from 'expo-router'; import { View, Text, StyleSheet } from 'react-native'; export default function HomeScreen() { return ( Home View details ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` ### `Link` 如何工作? ¥How does `Link` work? `Link` 默认将子项封装在 `` 中。你可以自定义使用不同的按钮组件。 ¥`Link` wraps the children in a `` by default. You can customize to use a different button component. 使用 `Link` 组件封装自定义按钮组件和 `asChild` 属性,将所有属性转发到 `Link` 组件的第一个子项。有关 `Link` 组件的 props 的更多信息,请参阅 [在页面之间导航](/router/navigating-pages/)。 ¥Use the `Link` component to wrap the custom button component and the `asChild` prop which forwards all props to the first child of the `Link` component. For more information on the `Link` component's props, see [Navigate between pages](/router/navigating-pages/). ## 群组 ¥Groups 创建一个组来组织类似的路由或应用的一部分。每个组都有一个布局文件,分组目录需要在括号 `(group)` 内命名。 ¥A group is created to organize similar routes or a section of the app. Each group has a layout file, and the grouped directory requires a name inside parentheses `(group)`. 例如,你有 `/` 和 `/details` 路由,它们可以在 app/(home) 目录中分组。这会将文件结构更新为: ¥For example, you have the `/` and `/details` routes which can be grouped inside **app/(home)** directory. This updates the file structure to: 你还需要添加 (home)/_layout.tsx,它用于定义 `/` 和 `/details` 路由的 `Stack` 导航器。 ¥You also need to add **(home)/_layout.tsx** which is used to define the `Stack` navigator for `/` and `/details` routes. ```tsx app/(home)/_layout.tsx|collapseHeight=440 import { Stack } from 'expo-router'; export default function HomeLayout() { return ( ); } ``` Root 布局文件也发生了变化,现在包括 (home) 组,该组进一步使用 (home)/index 作为应用的初始路由。 ¥The Root layout file also changes and now includes the **(home)** group which further uses **(home)/index** as the initial route of the app. ```tsx app/_layout.tsx import { Stack } from 'expo-router'; export default function RootLayout() { return ( ); } ``` > 注意:在上面的例子中,屏幕选项被移动到 (home)/_layout.tsx 文件。这意味着如果你在 Root 布局中向 Stack 导航器添加任何路由,它将不会使用与 Home 布局中的路由相同的屏幕选项。 > > ¥**Note:** In the above example, the screen options are moved to **(home)/_layout.tsx** file. This means if you add any route to the Stack navigator inside the Root layout, it will not use the same screen options as the routes inside the Home layout. ## 标签导航器 ¥Tab navigator 选项卡导航器是一种使用选项卡栏在应用的不同部分之间导航的常见模式。Expo Router 提供 `Tabs` 导航组件。 ¥A tab navigator is a common pattern to navigate between different sections of an app using a tab bar. Expo Router provides a `Tabs` navigation component. 例如,在当前文件结构中,你有两个不同的部分:主页(`/` 和 `/details` 路由)和设置(`/settings` 路由)。添加一个特殊目录(tabs),你可以将现有的 Home 路由文件移动到其中并创建一个 settings.tsx。 ¥For example, in the current file structure, you have two different sections: Home (`/` and `/details` routes) and Settings (`/settings` route). Adding a special directory **(tabs)**, you can move the existing Home route files inside it and create a **settings.tsx**. (选项卡) 内的任何文件或目录都将成为选项卡导航器中的路由。要使用标签栏在不同路由之间切换,你需要在此目录 (tabs)/_layout 中创建布局文件并导出 `TabLayout` 组件: ¥Any file or directory inside **(tabs)** becomes a route in the tab navigator. To switch between different routes using the tab bar, you need to create a layout file inside this directory **(tabs)/_layout** and export a `TabLayout` component: ```tsx app/(tabs)/_layout.tsx import { Tabs } from 'expo-router'; export default function TabLayout() { return ( ); } ``` > 注意:在 `TabLayout` 中,`(home)` 的现有 Stack 导航器现已嵌套。 > > ¥**Note:** In `TabLayout`, the existing Stack navigator for `(home)` is now nested. 要使其工作,请通过添加 (tabs) 作为第一条路由来更新 app/_layout.tsx 文件。 ¥To make this work, update the **app/_layout.tsx** file by adding **(tabs)** as the first route. ```tsx app/_layout.tsx import { Stack } from 'expo-router'; export default function RootLayout() { return ( ); } ``` ## 未找到路由 ¥Not found routes Expo Router 提供了一个特殊文件 +not-found.tsx,用于处理 404 路由。此路由文件匹配嵌套级别中所有不匹配的路由。 ¥Expo Router provides a special file **+not-found.tsx** which is used to handle routes that are 404s. This route file matches all unmatched routes from a nested level. 在应用目录中创建此文件: ¥Create this file in the **app** directory: ```tsx +not-found.tsx|collapseHeight=320 import { Link, Stack } from 'expo-router'; import { View, StyleSheet } from 'react-native'; export default function NotFoundScreen() { return ( <> Go to home screen ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` ## 动态路由 了解动态路由以及如何使用 Expo Router 库创建它们。 动态路由允许根据 URL 中嵌入的动态段匹配一个或多个路径。此段采用变量的形式,例如唯一标识符,并且你的应用事先不知道确切的段。 ¥A **dynamic route** allows matching one or multiple paths based on a dynamic segment embedded in the URL. This segment is in the form of a variable, such as a unique identifier, and your app doesn't know the exact segment ahead of time. 本指南介绍如何使用 Expo Router 处理动态路由。 ¥This guide explains how to handle dynamic routes with Expo Router. > 本指南继续在上一个 [基于文件的路由](/develop/file-based-routing/) 中使用的示例和应用目录结构的基础上构建。 > > ¥This guide continues to build on top of the example and the **app** directory structure used in the previous [File-based routing](/develop/file-based-routing/). ## 动态路由约定 ¥Dynamic route convention 通过将文件名称括在方括号中来创建路由的动态段。例如,[id].tsx。 ¥A dynamic segment of a route is created by wrapping a file's name in square brackets. For example, **[id].tsx**. > 什么是动态段?URL 中路径的任何部分都是动态的。例如,在显示用户列表的应用屏幕中,你可能有一个路径,例如 `/details/[id]`,其中 `[id]` 是动态段,并根据用户的 `id` 显示详细信息。 > > ¥**What is a dynamic segment?** Any segment of a path in a URL that is dynamic. For example, in an app screen where it displays a users list, you might have a path such as `/details/[id]` where the `[id]` is the dynamic segment and displays details based on the `id` of the user. ## 创建动态路由 ¥Create a dynamic route 让我们考虑以下应用目录结构: ¥Let's consider the following **app** directory structure: 在上面的文件结构中,`[id]` 用于显示路由 details/[id].tsx 的信息。相同的路由将根据 `id` 的值显示唯一信息: ¥In the above file structure, the `[id]` is used to display information for the route **details/[id].tsx**. The same route will display unique information based on the value of the `id`: | 路由 | 匹配的网址 | | --------------------- | ------------ | | **details/\[id].tsx** | `/details/1` | | **details/\[id].tsx** | `/details/2` | 此动态段约定确保当应用用户从主屏幕导航到详细信息屏幕时,他们会看到路由动态段的正确信息。 ¥This dynamic segment convention makes sure that when an app user navigates from the home screen to the details screen, they view the correct information for the dynamic segment of the route. ## 使用 `Link` 导航到动态路由 ¥Use `Link` to navigate to a dynamic route 通过静态或使用 `href` 对象向 `Link` 组件提供查询参数,可以从一条路由导航到一条动态路由。 ¥Navigating from one route to a dynamic route is done by providing query parameters to the `Link` component either statically or using the `href` object. 例如,以下代码允许你使用查询参数静态导航到动态路由: ¥For example, the following code allows you to navigate to the dynamic route statically using query parameters: ```tsx app/(home)/index.tsx|collapseHeight=300 import { Link } from 'expo-router'; import { View, Text, StyleSheet } from 'react-native'; export default function HomeScreen() { return ( Home View first user details View second user details ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` 你还可以使用 `href` 对象提供一个 `pathname`,它获取动态路由的值并传递 `params`: ¥You can also use the `href` object to provide a `pathname` which takes the value of the dynamic route and passes `params`: ```tsx app/(home)/index.tsx import { Link } from 'expo-router'; import { View, Text, StyleSheet } from 'react-native'; export default function HomeScreen() { return ( Home View user details ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` ## 从动态段访问参数 ¥Access parameters from dynamic segments URL 的动态段可以通过路由组件中的 [路由参数](/router/reference/url-parameters/) 访问。例如,你可以使用 [`useLocalSearchParams`](/router/reference/hooks/#uselocalsearchparams) 钩子,它返回所选路由的 URL 参数。 ¥Dynamic segments of a URL are accessible with a [route parameter](/router/reference/url-parameters/) in the route component. For example, you can use the [`useLocalSearchParams`](/router/reference/hooks/#uselocalsearchparams) hook which returns the URL parameters for the selected route. ```tsx app/(home)/details/[id].tsx|collapseHeight=300 import { useLocalSearchParams } from 'expo-router'; import { View, Text, StyleSheet } from 'react-native'; export default function DetailsScreen() { const { id } = useLocalSearchParams(); return ( Details of user {id} ); } const styles = StyleSheet.create({ container: { flex: 1, justifyContent: 'center', alignItems: 'center', }, }); ``` 当 `/` 推送 `/details/1` 时,`useLocalSearchParams` 返回 `{ id: '1' }`,因为 `/details/1` 是选定的路由。 ¥When `/` pushes `/details/1`, the `useLocalSearchParams` returns `{ id: '1' }` because `/details/1` is the selected route. ## 下一步 有关 Expo Router 的指南和参考列表,供进一步阅读。 如果你是第一次深入研究基于文件的路由框架,那么有很多关于 Expo Router 的知识需要学习。以下指南和参考资料将帮助你深入了解: ¥There's much to learn about Expo Router if you are diving into the file-based routing framework for the first time. The following guides and references will help you dive deep: ## 导航模式 ¥Navigation patterns ## 参考资料 ¥References # 用户界面 ## 启动画面和应用图标 了解如何向 Expo 项目添加启动画面和应用图标。 启动画面和应用图标是移动应用的基本元素。它们在用户体验和应用品牌推广中发挥着重要作用。本指南提供了如何创建它们并将其添加到你的应用的步骤。 ¥A splash screen and an app icon are fundamental elements of a mobile app. They play an important role in the user experience and branding of the app. This guide provides steps on how to create and add them to your app. Video Tutorial: [Create an App Icon and Splash Screen](https://www.youtube.com/watch?v=3Bsw8a1BJoQ) *** ## 启动画面 ¥Splash screen 启动屏幕,也称为启动屏幕,是用户打开你的应用时看到的第一个屏幕。当应用加载时它保持可见。你还可以使用原生 [启动画面 API](/versions/latest/sdk/splash-screen) 来控制启动屏幕消失时的行为。 ¥A splash screen, also known as a launch screen, is the first screen a user sees when they open your app. It stays visible while the app is loading. You can also control the behavior of when a splash screen disappears by using the native [SplashScreen API](/versions/latest/sdk/splash-screen). [`expo-splash-screen`](/versions/latest/sdk/splash-screen) 有一个内置的 [配置插件](/config-plugins/introduction),可让你配置属性,例如启动图标和背景颜色。 ¥The [`expo-splash-screen`](/versions/latest/sdk/splash-screen) has a built-in [config plugin](/config-plugins/introduction) that lets you configure properties such as the splash icon and background color. > **warning** 请勿使用 Expo Go 或开发版本来测试你的启动画面。Expo Go 在启动画面可见时渲染你的应用图标,这可能会干扰测试。开发版本包括 `expo-dev-client`,它有自己的启动画面,可能会导致冲突。相反,使用 [预览版本](/build/eas-json/#preview-builds) 或 [生产构建](/build/eas-json/#production-builds)。 > > ¥**Do not use Expo Go or a development build to test your splash screen**. Expo Go renders your app icon while the splash screen is visible, which can interfere with testing. Development builds include `expo-dev-client`, which has its own splash screen and may cause conflicts. **Instead, use a [preview build](/build/eas-json/#preview-builds) or a [production build](/build/eas-json/#production-builds)**. Step 1: ### Create a splash screen icon To create a splash screen icon, you can use this [Figma template](https://www.figma.com/community/file/1466490409418563617). It provides a bare minimum design for an icon and splash images for Android and iOS. **Recommended:** - Use a 1024x1024 image. - Use a **.png** file. - Use a transparent background. Step 2: ### Export the splash icon as a .png After creating a splash screen icon, export it as a **.png** and save it in the **assets/images** directory. By default, Expo uses **splash-icon.png** as the file name. If you decide to change the name of your splash screen file, make sure to use that in the next step. > **Note:** **Currently, only .png images are supported** to use as a splash screen icon in an Expo project. If you use another image format, making a production build of your app will fail. Step 3: ### Configure the splash screen icon Open the app config file, and under plugins, set the following properties: !!!IG0!!! To test your new splash screen, build your app for [internal distribution](/tutorial/eas/internal-distribution-builds) or for production, see guides on [Android](/tutorial/eas/android-production-build/) and [iOS](/tutorial/eas/ios-production-build/). !!!IG4!!! Note: Configuring properties separately for Android and iOS --- [`expo-splash-screen`](/versions/latest/sdk/splash-screen) also supports `android` and `ios` properties for configuring the splash screen for a specific platform. See the following example: !!!IG1!!! --- Note: Not using prebuild? --- If your app does not use [Expo Prebuild](/workflow/prebuild) (formerly the _managed workflow_) to generate the native **android** and **ios** directories, then changes in the app config will have no effect. For more information, see [how you can customize the configuration manually](https://github.com/expo/expo/tree/main/packages/expo-splash-screen#-installation-in-bare-react-native-projects). --- Note: Troubleshooting: New splash screen not appearing on iOS --- For SDK 51 and below, in iOS development builds, launch screens can sometimes remain cached between builds, making it harder to test new images. Apple recommends clearing the _derived data_ directory before rebuilding, this can be done with Expo CLI by running: ```sh $ npx expo run:ios --no-build-cache ``` See [Apple's guide on testing launch screens](https://developer.apple.com/documentation/technotes/tn3118-debugging-your-apps-launch-screen) for more information. --- ## App icon An app's icon is what your app users see on their device's home screen and app stores. Android and iOS have different and strict requirements. Step 1: ### Create an app icon To create an app icon, you can use this [Figma template](https://www.figma.com/community/file/1466490409418563617). It provides a bare minimum design for an icon and splash images for Android and iOS. Step 2: ### Export the icon image as a .png After creating an app icon, export it as **.png** and save it in the **assets/images** directory. By default, Expo uses **icon.png** as the file name. If you decide to use a different file name, make sure to use that in the next step. Step 3: ### Add the icon in app config Open the app config and add the local path as the value of [`icon`](/versions/latest/config/app/#icon) property to point it to your new app icon: !!!IG2!!! Note: Custom configuration tips for Android and iOS --- #### Android Further customization of the Android icon is possible using the [`android.adaptiveIcon`](/versions/latest/config/app/#adaptiveicon) property, which will override both of the previously mentioned settings. The Android Adaptive Icon is formed from two separate layers — a foreground image and a background color or image. This allows the OS to mask the icon into different shapes and also supports visual effects. For Android 13 and later, the OS supports a themed app icon that uses a wallpaper and theme to determine the color set by the device's theme. The design you provide should follow the [Android Adaptive Icon Guidelines](https://developer.android.com/develop/ui/views/launch/icon_design_adaptive) for launcher icons. You should also: - Use **.png** files. - Use the `android.adaptiveIcon.foregroundImage` property to specify the path to your foreground image. - Use the `android.adaptiveIcon.monochromeImage` property to specify the path to your monochrome image. - The default background color is white; to specify a different background color, use the `android.adaptiveIcon.backgroundColor` property. You can instead specify a background image using the `android.adaptiveIcon.backgroundImage` property. Make sure that it has the same dimensions as your foreground image. You may also want to provide a separate icon for older Android devices that do not support Adaptive Icons. You can do so with the `android.icon` property. This single icon would be a combination of your foreground and background layers. > See [Apple best practices](https://developer.apple.com/design/human-interface-guidelines/app-icons/#Best-practices) to ensure your icon looks professional, such as testing your icon on different wallpapers and avoiding text beside your product's wordmark. Provide an icon that's at least 512x512 pixels. #### iOS For iOS, your app's icon should follow the [Apple Human Interface Guidelines](https://developer.apple.com/design/human-interface-guidelines/app-icons/). You should also: - Use a **.png** file. - 1024x1024 is a good size. If you have an Expo project created using `npx create-expo-app`, [EAS Build](/build/setup/) will generate the other sizes for you. In case of a bare React Native project, generate the icons on your own. The largest size EAS Build generates is 1024x1024. - The icon must be exactly square. For example, a 1023x1024 icon is not valid. - Make sure the icon fills the whole square, with no rounded corners or other transparent pixels. The operating system will mask your icon when appropriate. - Use `ios.icon` to specify different icons for various system appearances (for example, dark and tinted) can be provided. If specified, this overrides the top-level icon key in the app config file. See the example below: !!!IG3!!! --- ## 安全区域 了解如何在 Expo 项目中添加屏幕组件的安全区域。 创建安全区域可确保你的应用屏幕内容定位正确。这意味着它不会被凹口、状态栏、主页指示器和其他属于设备物理硬件或由操作系统控制的界面元素重叠。当内容重叠时,它会被这些界面元素隐藏。 ¥Creating a safe area ensures your app screen's content is positioned correctly. This means it doesn't get overlapped by notches, status bars, home indicators, and other interface elements that are part of the device's physical hardware or are controlled by the operating system. When the content gets overlapped, it gets concealed by these interface elements. 以下是 Android 上应用屏幕内容被状态栏隐藏的示例。在 iOS 上,相同的内容被圆角、凹口和状态栏隐藏。 ¥Here's an example of an app screen's content getting concealed by the status bar on Android. On iOS, the same content is concealed by rounded corners, notch, and the status bar. ## 使用 `react-native-safe-area-context` 库 ¥Use `react-native-safe-area-context` library [`react-native-safe-area-context`](https://github.com/th3rdwave/react-native-safe-area-context) 提供了一个灵活的 API 来处理 Android 和 iOS 设备的安全区域插入。它还提供了一个 `SafeAreaView` 组件,你可以使用它代替 [``](https://rn.nodejs.cn/docs/view) 自动考虑屏幕组件中的安全区域。 ¥[`react-native-safe-area-context`](https://github.com/th3rdwave/react-native-safe-area-context) provides a flexible API for handling Android and iOS device's safe area insets. It also provides a `SafeAreaView` component that you can use instead of a [``](https://rn.nodejs.cn/docs/view) to account for safe areas automatically in your screen components. 使用该库,上一个示例的结果会发生变化,因为它会在安全区域内显示内容,如下所示: ¥Using the library, the result of the previous example changes as it displays the content inside a safe area, as shown below: ### 安装 ¥Installation 如果你使用 [这篇博文](/get-started/create-a-project/) 创建了项目,则可以跳过安装 `react-native-safe-area-context`。此库作为 Expo Router 库的对等依赖安装。否则,请通过运行以下命令进行安装: ¥You can skip installing `react-native-safe-area-context` if you have created a project using [the default template](/get-started/create-a-project/). This library is installed as peer dependency for Expo Router library. Otherwise, install it by running the following command: ```sh $ npx expo install react-native-safe-area-context ``` ### 用法 ¥Usage 你可以直接使用 [`SafeAreaView`](https://github.com/th3rdwave/react-native-safe-area-context#safeareaview) 来封装屏幕组件的内容。它是一个常规的 ``,安全区域插入应用为额外的填充或边距。 ¥You can directly use [`SafeAreaView`](https://github.com/th3rdwave/react-native-safe-area-context#safeareaview) to wrap the content of your screen's component. It is a regular `` with the safe area insets applied as extra padding or margin. ```tsx app/index.tsx import { Text } from 'react-native'; import { SafeAreaView } from 'react-native-safe-area-context'; export default function HomeScreen() { return ( Content is in safe area. ); } ``` Note: Using a different Expo template and don't have Expo Router installed? --- Import and add [`SafeAreaProvider`](https://github.com/th3rdwave/react-native-safe-area-context#safeareaprovider) to the root component file (such as **App.tsx**) before using `SafeAreaView` in your screen component. ```tsx App.tsx import { SafeAreaProvider } from 'react-native-safe-area-context'; export default function App() { return ( return ...; ); } ``` --- ## Alternate: `useSafeAreaInsets` hook Alternate to `SafeAreaView`, you can use [`useSafeAreaInsets`](https://github.com/th3rdwave/react-native-safe-area-context#usesafeareainsets) hook in your screen component. It provides direct access to the safe area insets, allowing you to apply padding for each edge of the `` using an inset from this hook. The example below uses the `useSafeAreaInsets` hook. It applies top padding to a `` using `insets.top`. ```tsx app/index.tsx import { Text, View } from 'react-native'; import { useSafeAreaInsets } from 'react-native-safe-area-context'; export default function HomeScreen() { const insets = useSafeAreaInsets(); return ( Content is in safe area. ); } ``` The hook provides the insets in the following object: ```ts { top: number, right: number, bottom: number, left: number } ``` ## Additional information ### Minimal example Below is a minimal working example that uses the `useSafeAreaInsets` hook to apply top padding to a view. #### Using react-native-safe-area-context ```tsx collapseHeight=320 import { Text, View } from 'react-native'; import { SafeAreaProvider, useSafeAreaInsets } from 'react-native-safe-area-context'; function HomeScreen() { const insets = useSafeAreaInsets(); return ( Content is in safe area. ); } export default function App() { return ( ); } ``` ### 与 React 导航一起使用 ¥Usage with React Navigation 默认情况下,React Navigation 支持安全区域并使用 `react-native-safe-area-context` 作为对等依赖。有关详细信息,请参阅 [React 导航文档](https://react-navigation.nodejs.cn/docs/handling-safe-area/)。 ¥By default, React Navigation supports safe areas and uses `react-native-safe-area-context` as a peer dependency. For more information, see the [React Navigation documentation](https://react-navigation.nodejs.cn/docs/handling-safe-area/). ### 与 Web 一起使用 ¥Usage with web 如果你的目标是 Web,请按照 [使用 Expo CLI 内置的 Chrome DevTools](#usage) 中的说明设置 `SafeAreaProvider`。如果你正在进行服务器端渲染 (SSR),请参阅库文档中的 [Web SSR 部分](https://github.com/th3rdwave/react-native-safe-area-context#web-ssr)。 ¥If you are targeting the web, set up `SafeAreaProvider` as described in the [usage section](#usage). If you are doing server-side rendering (SSR), see the [Web SSR section](https://github.com/th3rdwave/react-native-safe-area-context#web-ssr) in the library's documentation. ## 系统栏 了解如何在你的 Expo 项目中处理和自定义系统栏,以实现安全区域和无边框布局。 系统栏是位于屏幕边缘的 UI 元素,提供必要的设备信息和导航控件。根据移动操作系统的不同,它们包括状态栏([安卓](https://developer.android.com/design/ui/mobile/guides/foundations/system-bars) 和 [iOS 系统](https://developer.apple.com/design/human-interface-guidelines/status-bars))、标题栏(仅限 [安卓](https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b#:~:text=or%20SHORT_EDGES.-,Caption%20bars,-When%20your%20app))、导航栏([安卓](https://developer.android.com/design/ui/mobile/guides/foundations/system-bars#navigation-bar) 和 [iOS 系统](https://developer.apple.com/design/human-interface-guidelines/navigation-bars))以及主页指示器(仅限 iOS)。 ¥System bars are the UI elements at the edges of the screen that provide essential device information and navigation controls. Depending on the mobile OS, they include the status bar ([Android](https://developer.android.com/design/ui/mobile/guides/foundations/system-bars) and [iOS](https://developer.apple.com/design/human-interface-guidelines/status-bars)), caption bar ([Android](https://medium.com/androiddevelopers/insets-handling-tips-for-android-15s-edge-to-edge-enforcement-872774e8839b#:~:text=or%20SHORT_EDGES.-,Caption%20bars,-When%20your%20app) only), navigation bar ([Android](https://developer.android.com/design/ui/mobile/guides/foundations/system-bars#navigation-bar) and [iOS](https://developer.apple.com/design/human-interface-guidelines/navigation-bars)), and home indicator (iOS only). 这些组件用于显示设备信息,例如电池电量、时间、通知提醒,并提供从设备界面任何位置与设备的直接交互。例如,无论应用用户当前正在使用哪个应用,都可以下拉状态栏来访问快速设置和通知。 ¥These components are used to display device information such as battery level, time, notification alerts, and provide direct interaction with the device from anywhere in the device's interface. For example, an app user can pull down the status bar to access quick settings and notifications regardless of which app they're currently using. 系统栏是移动体验的基础,了解如何正确使用它们对于创建你的应用至关重要。 ¥System bars are fundamental to the mobile experience, and understanding how to work with them properly is important for creating your app. ## 使用安全区域处理重叠 ¥Handling overlaps using safe areas 你的部分应用内容可能会绘制在系统栏后面。为此,你需要正确定位应用内容,避免重叠并确保系统栏中的控件可见。 ¥Some of your app's content may draw behind the system bars. To handle this, you need to position your app's content correctly by avoiding the overlap and ensuring that the controls from the system bars are present. 以下指南将引导你了解如何使用 `SafeAreaView` 或钩子直接在屏幕的每个边缘应用内嵌图 (Insets)。 ¥The following guide walks you through how to use `SafeAreaView` or a hook to apply insets directly for each edge of the screen. ### Android 上的安全区域和无边框布局 ¥Safe areas and edge-to-edge layout on Android 在 [Android 上的边到边](https://expo.dev/blog/edge-to-edge-display-now-streamlined-for-android) 之前,半透明的状态栏和导航栏很常见。采用这种方法,这些状态栏后面绘制的内容已经位于其下方,通常无需考虑安全区域。 ¥Before [edge-to-edge on Android](https://expo.dev/blog/edge-to-edge-display-now-streamlined-for-android), it was common to have a translucent status bar and navigation bar. With this approach, the content drawn behind these bars was already underneath them, and it was typically not necessary to factor in safe areas. 现在,[Android 上的边到边](https://expo.dev/blog/edge-to-edge-display-now-streamlined-for-android),你需要使用安全区域来确保内容不会与系统栏重叠。 ¥Now, [with edge-to-edge on Android](https://expo.dev/blog/edge-to-edge-display-now-streamlined-for-android), you will need to use safe areas to ensure that content does not overlap with system bars. ## 自定义系统栏 ¥Customizing system bars 系统栏可以自定义,以匹配你的应用设计,并在不同场景下提供更好的可视性。使用 Expo 时,有两个库可用于此操作:`expo-status-bar` 和 `expo-navigation-bar`(仅限 Android)。 ¥System bars can be customized to match your app's design and provide better visibility in different scenarios. When using Expo, there are two libraries available for this: `expo-status-bar` and `expo-navigation-bar` (Android only). ### 状态栏配置 ¥Status bar configuration 状态栏显示在 Android 和 iOS 屏幕的顶部。你可以使用 [`expo-status-bar`](/versions/latest/sdk/status-bar) 对其进行自定义。它提供了一个 `StatusBar` 组件,你可以使用该组件的 [`style`](/versions/latest/sdk/status-bar/#style) 属性或 [`setStatusBarStyle`](/versions/latest/sdk/status-bar/#statusbarsetstatusbarstylestyle-animated) 方法在应用运行时控制状态栏的外观: ¥The status bar appears at the top of the screen on both Android and iOS. You can customize it using [`expo-status-bar`](/versions/latest/sdk/status-bar). It provides a `StatusBar` component that you can use to control the appearance of the status bar while your app is running using the [`style`](/versions/latest/sdk/status-bar/#style) property or the [`setStatusBarStyle`](/versions/latest/sdk/status-bar/#statusbarsetstatusbarstylestyle-animated) method: ```tsx app/_layout.tsx import { StatusBar } from 'expo-status-bar'; export default function RootLayout() { <> {/* Use light text instead of dark text in the status bar to provide more contrast with a dark background. */} ; } ``` > 注意:在 Expo 默认模板中,`style` 属性设置为 `auto`。它会根据你应用当前使用的配色方案(亮色或暗色模式)自动选择合适的样式。 > > ¥**Note:** In Expo default template, the `style` property is set to `auto`. It automatically picks the appropriate style depending on the color scheme (light or dark mode) currently used by your app. 要控制 `StatusBar` 的可见性,可以将 [`hidden`](/versions/latest/sdk/status-bar/#hidden) 属性设置为 `true` 或使用 [`setStatusBarHidden`](/versions/latest/sdk/status-bar/#statusbarsetstatusbarhiddenhidden-animation) 方法。 ¥To control the `StatusBar` visibility, you can set the [`hidden`](/versions/latest/sdk/status-bar/#hidden) property to `true` or use the [`setStatusBarHidden`](/versions/latest/sdk/status-bar/#statusbarsetstatusbarhiddenhidden-animation) method. 在 Android 上启用无边框屏幕后,`expo-status-bar` 中依赖于不透明状态栏 [不可用](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge) 的功能将无法使用。只能自定义样式和可见性。其他属性将不执行任何操作并发出警告。 ¥**With edge-to-edge enabled on Android, features from `expo-status-bar` that depend on an opaque status bar [are unavailable](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge)**. It's only possible to customize the style and visibility. Other properties will no-op and warn. ### 导航栏配置(仅限 Android) ¥Navigation bar configuration (Android only) 在 Android 设备上,导航栏会显示在屏幕底部。你可以使用 [`expo-navigation-bar`](/versions/latest/sdk/navigation-bar) 库对其进行自定义。它提供了一个 `NavigationBar` 组件,你可以使用该组件的 [`setStyle`](/versions/latest/sdk/navigation-bar/#navigationbarsetstylestyle) 方法设置导航栏的样式: ¥On Android devices, the Navigation Bar appears at the bottom of the screen. You can customize it using the [`expo-navigation-bar`](/versions/latest/sdk/navigation-bar) library. It provides a `NavigationBar` component that you can use to set the style of the navigation bar using the [`setStyle`](/versions/latest/sdk/navigation-bar/#navigationbarsetstylestyle) method: ```tsx app/_layout.tsx import { NavigationBar } from 'expo-navigation-bar'; import { useEffect } from 'react'; useEffect(() => { if (Platform.OS === 'android') { // Set the navigation bar style NavigationBar.setStyle('dark'); } }, []); ``` 要控制 `NavigationBar` 的可见性,可以使用 [`setVisibilityAsync`](/versions/latest/sdk/navigation-bar/#navigationbarsetvisibilityasyncvisibility) 方法。 ¥To control the `NavigationBar` visibility, you can use the [`setVisibilityAsync`](/versions/latest/sdk/navigation-bar/#navigationbarsetvisibilityasyncvisibility) method. 在 Android 上启用无边框屏幕后,`expo-navigation-bar` 中依赖于不透明导航栏 [不可用](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge) 的功能将无法使用。只能自定义样式和可见性。其他属性将不执行任何操作并发出警告。 ¥**With edge-to-edge enabled on Android, features from `expo-navigation-bar` that depend on an opaque navigation bar [are unavailable](https://developer.android.com/about/versions/15/behavior-changes-15#edge-to-edge)**. It's only possible to customize the style and visibility. Other properties will no-op and warn. ## 字体 了解如何使用本地文件或 Google Font 包将自定义字体集成到应用中 Android 和 iOS 都有自己的一套平台字体。为了提供一致的用户体验并增强应用的品牌,你可以使用自定义字体。 ¥Android and iOS come with their own set of platform fonts. To provide a consistent user experience and enhance your app's branding, you can use custom fonts. 本指南介绍了向项目中添加和加载自定义字体的不同方法,还提供了与字体相关的其他信息。 ¥This guide covers different ways you can add and load a custom font into your project and also provides additional information related to fonts. ## 添加自定义字体 ¥Add a custom font 有两种方法可以将自定义字体添加到项目中: ¥There are two ways you can add a custom font into your project: * 将字体文件添加到你的本地资源中。例如,assets/fonts 目录中的字体文件。 ¥Add a font file into your local assets. For example, a font file in the **assets/fonts** directory. * 安装 Google 字体包。例如,安装 [`@expo-google-fonts/inter`](https://www.npmjs.com/package/@expo-google-fonts/inter) 包。 ¥Install a Google Font package. For example, installing [`@expo-google-fonts/inter`](https://www.npmjs.com/package/@expo-google-fonts/inter) package. ### 支持的字体格式 ¥Supported font formats Expo SDK 正式支持 Android、iOS 和 Web 平台上的 OTF 和 TTF 字体格式。如果你的字体是其他字体格式,则必须设置高级配置以在你的项目中支持该格式。 ¥Expo SDK officially supports OTF and TTF font formats across Android, iOS and web platforms. If your font is in another font format, you have to set up advanced configuration to support that format in your project. ### 可变字体 ¥Variable fonts 可变字体(包括 OTF 和 TTF 格式的可变字体实现)并非所有平台都支持。为了获得完整的平台支持,请使用静态字体。或者,使用 [fontTools](https://fonttools.readthedocs.io/en/latest/varLib/mutator.html) 等实用程序从变量字体中提取你想要使用的特定轴配置,并将其保存为单独的字体文件。 ¥Variable fonts, including variable font implementations in OTF and TTF, do not have support across all platforms. For full platform support, use static fonts. Alternatively, use a utility such as [fontTools](https://fonttools.readthedocs.io/en/latest/varLib/mutator.html) to extract the specific axis configuration you want to use from the variable font and save it as a separate font file. ### 如何在 OTF 和 TTF 之间进行选择 ¥How to choose between OTF and TTF 如果你使用的字体同时具有 OTF 和 TTF 版本,则最好使用 OTF。.otf 文件比 .ttf 文件小。有时,OTF 在某些情况下也会渲染得更好一些。 ¥If the font you're using has both OTF and TTF versions, prefer OTF. The **.otf** files are smaller than **.ttf** files. Sometimes, OTF also renders slightly better in certain contexts. ## 使用本地字体文件 ¥Use a local font file 将文件复制到项目的 assets/fonts 目录中。 ¥Copy the file into your project's **assets/fonts** directory. > **info** assets/fonts 目录路径是 React Native 应用中放置字体文件的常见约定。如果你遵循自定义约定,你可以将这些文件放在其他地方。 > > ¥**assets/fonts** directory path is a common convention in React Native apps to put font files. You can place these files elsewhere if you follow a custom convention. 在项目中使用本地字体文件的两种方法: ¥Two ways to use the local font file in your project: * 使用 [`expo-font` 配置插件](/versions/latest/sdk/font/#configuration-in-app-config) 嵌入字体文件。 ¥Embed the font file with [`expo-font` config plugin](/versions/latest/sdk/font/#configuration-in-app-config). * 在运行时使用 [`useFonts`](/versions/latest/sdk/font/#usefontsmap) 钩子异步加载字体文件。 ¥Loading the font file with [`useFonts`](/versions/latest/sdk/font/#usefontsmap) hook at runtime asynchronously. ### 使用 `expo-font` 配置插件 ¥With `expo-font` config plugin `expo-font` 配置插件允许在项目的原生代码中嵌入一个或多个字体文件。它支持 Android 和 iOS 的 `ttf` 和 `otf`,而 `woff` 和 `woff2` 仅在 iOS 上受支持。这是向你的应用添加字体的推荐方法,因为它具有以下优点: ¥The `expo-font` config plugin allows embedding one or more font files in your project's native code. It supports `ttf` and `otf` for both Android and iOS, and `woff` and `woff2` are supported on iOS only. This is the recommended method for adding fonts to your app due to its benefits: * 当应用在设备上启动时,字体立即可用。 ¥Fonts are available immediately when the app starts on a device. * 应用启动时,无需额外代码即可异步加载项目中的字体。 ¥No additional code required to load fonts in a project asynchronously when the app starts. * 由于字体已打包在应用中,因此它们在安装应用的所有设备上始终可用。 ¥Fonts are consistently available across all devices where the app is installed because they're bundled within the app. 但是,这种方法也有一些限制: ¥However, this method also has some limitations: * 不适用于 Expo Go,因为此方法需要 [创建开发构建](/develop/development-builds/create-a-build/)。 ¥Doesn't work with Expo Go since this method requires [creating a development build](/develop/development-builds/create-a-build/). 要在项目中嵌入字体,请按照以下步骤操作: ¥To embed a font in a project, follow the steps below: Step 1: After adding a custom font file in your project, install the `expo-font` library. ```sh $ npx expo install expo-font ``` Step 2: Add the config plugin to your [app config](/versions/latest/config/app/#plugins) file. The configuration must contain the path to the font file using [`fonts`, `android` or `ios`](/versions/latest/sdk/font/#configurable-properties) properties which take an array of one or more font definitions. The path to each font file is relative to the project's root. The example below showcases all valid ways a font can be specified: as an array of objects that specify `fontFamily` and other properties, or an array of paths to font files. For Android, you can specify the `fontFamily`, `weight`, and optionally `style` (defaults to `"normal"`), which will embed the fonts as native [XML resources](https://developer.android.com/develop/ui/views/text-and-emoji/fonts-in-xml). If you provide only the font file paths in an array, the file name becomes the font family name on Android. iOS always extracts the font family name from the font file itself. If you plan to refer to fonts using just the `fontFamily`, provide an array of font paths (see `FiraSans-MediumItalic.ttf` below) and follow our [recommendation for file naming](#how-to-determine-which-font-family-name-to-use). If you want to refer to fonts using a combination of `fontFamily`, `weight`, and `style`, provide an array of objects (see `Inter` below). !!!IG3!!! Step 3: After embedding the font with the config plugin, create a [new development build](/develop/development-builds/create-a-build/) and install it on your device or Android Emulator or iOS Simulator. You can use the font with `` by specifying the `fontFamily` style prop. The examples below correspond to the fonts defined in the configuration above. !!!IG4!!! - **Android:** Copy font files to **android/app/src/main/assets/fonts**. - **iOS:** See [Adding a Custom Font to Your App](https://developer.apple.com/documentation/uikit/text_display_and_fonts/adding_a_custom_font_to_your_app) in the Apple Developer documentation. #### How to determine which font family name to use - If you provide fonts as an array of file paths (as described above), on Android, the file name (without the extension) becomes the font family name. On iOS, the font family name is read from the font file itself. We recommend naming the font file same as its [PostScript name](#what-is-postscript-name-of-a-font) so the font family name is consistent on both platforms. - If you use the object syntax, provide the "Family Name". This can be found in the Font Book app on macOS, [fontdrop.info](https://fontdrop.info/) or other programs. Note: What is PostScript name of a font file? --- The **PostScript name** of a font file is a unique identifier assigned to the font that follows Adobe's PostScript standard. It is used by operating systems and apps to refer to the font. It is not a font's **display name**. For example, Inter Black font file's PostScript name is `Inter-Black`. _Screenshot from Font Book app on macOS._ --- ### With `useFonts` hook The `useFonts` hook from `expo-font` library allows loading the font file asynchronously. This hook keeps track of the loading state and loads the font when an app is initialized. It works with all Expo SDK versions and with Expo Go. To load a font in a project using `useFonts` hook, follow the steps below: Step 1: After adding a custom font file in your project, install the `expo-font` and `expo-splash-screen` libraries. ```sh $ npx expo install expo-font expo-splash-screen ``` The [`expo-splash-screen`](/versions/latest/sdk/splash-screen/) library provides `SplashScreen` component that you can use to prevent rendering the app until the font is loaded and ready. Step 2: Map the font file using the `useFonts` hook in a top level component such as the root layout (**app/layout.tsx**) file in your project: !!!IG5!!! Step 3: Use the font on the `` by using `fontFamily` style prop in a React component: !!!IG6!!! ## Use Google Fonts Expo has first-class support for all fonts listed in [Google Fonts](https://fonts.google.com/). They are available using [`@expo-google-fonts`](https://github.com/expo/google-fonts) library. With any of the font package from this library, you can quickly integrate that font and its variants. Two ways to use a Google Font in your project: - Embed the installed font with [`expo-font` config plugin](/versions/latest/sdk/font/#configuration-in-appjsonappconfigjs). - Load the installed font with [`useFonts`](/versions/latest/sdk/font/#usefontsmap) hook at runtime asynchronously. ### With `expo-font` config plugin > **Note:** Embedding a Google Font using `expo-font` config plugin has same benefits and limitations as embedding a custom font on your own. See [using a local font file with `expo-font` config plugin](#with-expo-font-config-plugin) for more information. Step 1: Install the font package. For example, to use Inter Black font, install the [`@expo-google-fonts/inter`](https://www.npmjs.com/package/@expo-google-fonts/inter) package with the command below. ```sh $ npx expo install expo-font @expo-google-fonts/inter ``` Step 2: Add the config plugin to your [app config](/versions/latest/config/app/#plugins) file. The configuration must contain the path to the font file using [`fonts`](/versions/latest/sdk/font/#configurable-properties) property which takes an array of one or more font files. The path to the font file is defined from the font package inside the `node_modules` directory. For example, if you have a font package named `@expo-google-fonts/inter`, then the name of the file is **Inter_900Black.ttf**. !!!IG7!!! Step 3: After embedding the font with the config plugin, create a [new development build](/develop/development-builds/create-a-build/) and install it on your device or Android Emulator or iOS Simulator. On Android, you can use the font file name. For example, `Inter_900Black`. On iOS, use the font and its weight name ([PostScript name](#what-is-postscript-name-of-a-font)). The example below demonstrates how to use [`Platform`](https://rn.nodejs.cn/docs/platform-specific-code#platform-module) to select the correct font family name for each platform: !!!IG14!!! !!!IG8!!! ### With `useFonts` hook > **Note:** Loading a Google Font using `useFonts` hook has same benefits and limitations as embedding a custom font on your own. See [using a local font file with `useFonts` hook](#with-usefonts-hook) for more information. Each google Fonts package provides the `useFonts` hook to load the fonts asynchronously. This hook keeps track of the loading state and loads the font when an app is initialized. The font package also imports the font file so you don't have to explicitly import it. Step 1: Install the Google Fonts package, `expo-font` and `expo-splash-screen` libraries. ```sh $ npx expo install @expo-google-fonts/inter expo-font expo-splash-screen ``` The [`expo-splash-screen`](/versions/latest/sdk/splash-screen/) library provides `SplashScreen` component that you can use to prevent rendering the app until the font is loaded and ready. Step 2: After installing the font package, map the font using the `useFonts` hook in a top level component such as the root layout (**app/layout.tsx**) file in your project: !!!IG9!!! Step 3: Use the font on the `` by using `fontFamily` style prop in a React component: !!!IG10!!! ## Additional information ### Minimal example !!!IG15!!! ### Beyond OTF and TTF If your font is in format other than OTF or TTF, you have to [customize the Metro bundler configuration to include it as an extra asset](/guides/customizing-metro#adding-more-file-extensions-to-assetexts) for it to work. In some cases, rendering a font format that a platform doesn't support may cause your app to crash. For reference, the following table provides the list formats that work on each native platform: | Format | Android | iOS | Web | | ------ | ----------- | ----------- | ----------- | | bdf | | | | | dfont | | | | | eot | | | | | fon | | | | | otf | | | | | ps | | | | | svg | | | | | ttc | | | | | ttf | | | | | woff | | | | | woff2 | | | | ### Platform built-in fonts If you don't want to use a custom font by specifying a `fontFamily`, platform's default font will be used. Each platform has a set of built in fonts. On Android, the default font is Roboto. On iOS, it's SF Pro. A platform's default font is usually easy-to-read. However, don't be surprised when the system default font is changed to use another font that is not easy to read. In this case, use your custom font so you have precise control over what the user will see. ### Handle `@expo/vector-icons` initial load When the icons from `@expo/vector-icons` library load for the first time, they appear as invisible icons in your app. Once they load, they're cached for all the app's subsequent usage. To avoid showing invisible icons on your app's first load, preload during the initial loading screen with [`useFonts`](/versions/latest/sdk/font/#usefontsmap). For example: !!!IG11!!! Now, you can use any icon from the `Ionicons` library in a React component: !!!IG12!!! !!!IG16!!! ### Loading a remote font directly from the web > **warning** **If you're loading remote fonts, make sure they are being served from an origin with CORS properly configured**. If you don't do this, your remote font might not load properly on the web platform. Loading fonts from a local asset is the safest way to load a font in your app. When including fonts as local assets, after you submit your app to the app stores, these fonts are bundled with the app download and will be available immediately. You don't have to worry about CORS or other potential issues. However, loading a font file directly from web is done by replacing the `require('./assets/fonts/FontName.otf')` with the URL of your font as shown in the example below. #### Using a remote font !!!IG13!!! ## 资源 了解如何在项目中使用静态资源,包括图片、视频、声音、数据库文件和字体。 静态资源是与应用的二进制文件(原生二进制文件)打包在一起的文件。此文件类型不是包含应用代码的应用 JavaScript 打包包的一部分。常见的静态资源类型包括图片、视频、声音、SQLite 的数据库文件和字体。这些资源可以从你的项目本地提供,也可以通过网络远程提供。 ¥A **static asset** is a file that is bundled with your app's binary (native binary). This file type is not part of your app's JavaScript bundle which contain your app's code. Common types of static assets include images, videos, sounds, database files for SQLite, and fonts. These assets can be served locally from your project or remotely over the network. 本指南介绍了在项目中加载和使用静态资源的不同方式,还提供了有关如何优化和最小化资源的其他信息。 ¥This guide covers different ways you can load and use static assets in your project and also provides additional information on how to optimize and minify assets. ## 在本地提供资源 ¥Serve an asset locally 当资源存储在项目的文件系统中时,它可以在构建时嵌入到应用二进制文件中或在运行时加载。你可以使用 `require` 或 `import` 语句将其像 JavaScript 模块一样导入。 ¥When an asset is stored in your project's file system, it can be embedded in your app binary at build time or loaded at runtime. You can import it like a JavaScript module using `require` or `import` statements. 例如,要在 App.js 中渲染名为 example.png 的图片,你可以使用 `require` 从项目的 assets/images 目录导入图片并将其传递给 `` 组件: ¥For example, to render an image called **example.png** in **App.js**, you can use `require` to import the image from the project's **assets/images** directory and pass it to the `` component: ```tsx app/index.tsx ``` 在上面的例子中,打包器读取导入图片的元数据并自动提供宽度和高度。欲了解更多信息,请参阅 [静态图片资源](https://rn.nodejs.cn/docs/images#static-image-resources)。 ¥In the above example, the bundler reads the imported image's metadata and automatically provides the width and height. For more information, see [Static Image Resources](https://rn.nodejs.cn/docs/images#static-image-resources). `expo-image` 和 `expo-file-system` 等库的工作方式与使用本地资源的 `` 组件类似。 ¥Libraries such as `expo-image` and `expo-file-system` work similarly to the `` component with local assets. ### 资源如何在本地提供服务 ¥How are assets served locally 在开发过程中,本地存储的资源通过 HTTP 提供服务。它们会在生产应用的构建时自动打包到你的应用二进制文件中,并从设备上的磁盘提供服务。 ¥Locally stored assets are served over HTTP in development. They are automatically bundled into your app binary at the build time for production apps and served from disk on a device. ### 使用 `expo-asset` 配置在构建时加载资源插件 ¥Load an asset at build time with `expo-asset` config plugin > 注意:`expo-asset` 配置插件仅适用于 SDK 51 及更高版本。如果你使用的是较旧的 SDK,则可以加载 [使用 `useAssets` 钩子](#load-an-asset-at-runtime-with-useassets-hook)。 > > ¥**Note:** The `expo-asset` config plugin is only available for SDK 51 and above. If you are using an older SDK, you can load a [using the `useAssets` hook](#load-an-asset-at-runtime-with-useassets-hook). 要在构建时加载资源,你可以使用 `expo-asset` 库中的 [配置插件](/versions/latest/sdk/asset/#example-appjson-with-config-plugin)。该插件会将资源文件嵌入到你的原生项目中。 ¥To load an asset at build time, you can use the [config plugin](/versions/latest/sdk/asset/#example-appjson-with-config-plugin) from the `expo-asset` library. This plugin will embed the asset file in your native project. Step 1: Install the `expo-asset` library. ```sh $ npx expo install expo-asset ``` Step 2: Add the config plugin to your project's [app config](/versions/latest/config/app/#plugins) file. The configuration must contain the path to the asset file using [`assets`](/versions/latest/sdk/asset/#configurable-properties) property which takes an array of one or more files or directories to link to the native project. The path to each asset file must be relative to your project's root since the app config file is located in the project's root directory. ```json app.json { "expo": { "plugins": [ [ "expo-asset", { "assets": ["./assets/images/example.png"] } ] ] } } ``` Step 3: After embedding the asset with the config plugin, [create a new development build](/develop/development-builds/create-a-build/). Now, you can import and use the asset in your project without using a `require` or an `import` statement. For example, the **example.png** is linked by the above config plugin. You can directly import it into your component and use its resource name as the URI. Note that when rendering assets without using `require`, you need to explicitly provide a width / height. ```tsx app/index.tsx import { Image } from 'expo-image'; export default function HomeScreen() { return ; } ``` > **info** Different file formats are supported with the `expo-asset` config plugin. For more information on these formats, see [Assets API reference](/versions/latest/sdk/asset/#configurable-properties). If you don't see a file format supported by the config plugin, you can use the [`useAssets`](#load-an-asset-at-runtime-with-useassets-hook) hook to load the asset at runtime. ### Load an asset at runtime with `useAssets` hook The `useAssets` hook from `expo-asset` library allows loading assets asynchronously. This hook downloads and stores an asset locally and after the asset is loaded, it returns a list of that asset's instances. Step 1: Install the `expo-asset` library. ```sh $ npx expo install expo-asset ``` Step 2: Import the [`useAssets`](/versions/latest/sdk/asset/#useassetsmoduleids) hook from the `expo-asset` library in your screen component: ```tsx app/index.tsx import { useAssets } from 'expo-asset'; export default function HomeScreen() { const [assets, error] = useAssets([ require('path/to/example-1.jpg'), require('path/to/example-2.png'), ]); return assets ? : null; } ``` ## Serve an asset remotely When an asset is served remotely, it is not bundled into the app binary at build time. You can use the URL of the asset resource in your project if it is hosted remotely. For example, pass the URL to the `` component to render a remote image: ```jsx App.js import { Image } from 'expo-image'; function App() { return ( ); } ``` There is no guarantee about the availability of images served remotely using a web URL because an internet connection may not be available, or the asset might be removed. Additionally, loading assets remotely also requires you to provide an asset's metadata. In the above example, since the bundler cannot retrieve the image's width and height, those values are passed explicitly to the `` component. If you don't, the image will default to 0px by 0px. ## Additional information ### Manual optimization methods #### Images You can compress images using the following: - [`guetzli`](https://github.com/google/guetzli) - [`pngcrush`](https://pmt.sourceforge.io/pngcrush/) - [`optipng`](http://optipng.sourceforge.net/) Some image optimizers are lossless. They re-encode your image to be smaller without any change or loss in the pixels displayed. When you need each pixel to be untouched from the original image, a lossless optimizer and a lossless image format like PNG are a good choice. Other image optimizers are lossy. The optimized image differs from the original image. Often, lossy optimizers are more efficient because they discard visual information that reduces file size while making the image look nearly identical to humans. Tools like `imagemagick` can use comparison algorithms like [SSIM](https://en.wikipedia.org/wiki/Structural_similarity) to show how similar two images look. It's quite common for an optimized image that is over 95% similar to the original image to be far less than 95% of the original file size. #### Other assets For assets like GIFs or videos, or non-code and non-image assets, it's up to you to optimize and minify those assets. > 注意:GIF 是一种非常低效的格式。现代视频编解码器可以生成更小、质量更好的文件。 ¥**Note**: GIFs are a very inefficient format. Modern video codecs can produce significantly smaller file sizes with better quality. ### 字体 ¥Fonts 有关如何向应用添加自定义字体的更多信息,请参阅 [添加自定义字体](/develop/user-interface/fonts/#add-a-custom-font)。 ¥See [Add a custom font](/develop/user-interface/fonts/#add-a-custom-font) for more information on how to add a custom font to your app. ## 颜色主题 了解如何在你的应用中支持浅色和夜间模式。 应用支持浅色和深色配色方案很常见。以下是 Expo 项目中支持两种模式的示例: ¥It's common for apps to support light and dark color schemes. Here is an example of how supporting both modes looks in an Expo project: ## 配置 ¥Configuration > **info** 对于 Android 和 iOS 项目,需要进行其他配置才能支持在明夜间模式之间切换。对于 Web,无需额外配置。 > > ¥For Android and iOS projects, additional configuration is required to support switching between light and dark mode. For web, no additional configuration is required. 要配置支持的外观样式,你可以在项目的 [应用配置](/versions/latest/config/app) 中使用 [`userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle) 属性。默认情况下,当你使用 [默认模板](/get-started/create-a-project/) 创建新项目时,此属性默认设置为 `automatic`。 ¥To configure supported appearance styles, you can use the [`userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle) property in your project's [app config](/versions/latest/config/app). By default, this property is set to `automatic` when you create a new project with the [default template](/get-started/create-a-project/). 这是一个配置示例: ¥Here is an example configuration: ```json app.json { "expo": { "userInterfaceStyle": "automatic" } } ``` 你还可以通过将 [`android.userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle-2) 或 [`ios.userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle-1) 设置为首选值来为特定平台配置 `userInterfaceStyle` 属性。 ¥You can also configure `userInterfaceStyle` property for a specific platforms by setting either [`android.userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle-2) or [`ios.userInterfaceStyle`](/versions/latest/config/app/#userinterfacestyle-1) to the preferred value. > **info** 如果此属性不存在,应用将默认为 `light` 样式。 > > ¥The app will default to the `light` style if this property is absent. 创建开发版本时,你必须安装 [`expo-system-ui`](/versions/latest/sdk/system-ui/#installation) 以支持 Android 的外观样式。否则,`userInterfaceStyle` 属性将被忽略。 ¥When you are creating a development build, you have to install [`expo-system-ui`](/versions/latest/sdk/system-ui/#installation) to support the appearance styles for Android. Otherwise, the `userInterfaceStyle` property is ignored. ```sh $ npx expo install expo-system-ui ``` 如果项目配置错误且未安装 `expo-system-ui`,则终端中将显示以下警告: ¥If the project is misconfigured and doesn't have `expo-system-ui` installed, the following warning will be shown in the terminal: ```sh » android: userInterfaceStyle: Install expo-system-ui in your project to enable this feature. ``` 还可以使用以下命令检查项目是否配置错误: ¥You can also use the following command to check if the project is misconfigured: ```sh $ npx expo config --type introspect ``` Note: Using bare React Native app? --- #### Android Ensure that the `uiMode` flag is present on your `MainActivity` (and any other activities where this behavior is desired) in **AndroidManifest.xml**: ```xml ``` Implement the `onConfigurationChanged` method in **MainActivity.java**: ```java import android.content.Intent; import android.content.res.Configuration; public class MainActivity extends ReactActivity { @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); Intent intent = new Intent("onConfigurationChanged"); intent.putExtra("newConfig", newConfig); sendBroadcast(intent); } } ``` #### iOS You can configure supported styles with the [`UIUserInterfaceStyle`](https://developer.apple.com/documentation/bundleresources/information_property_list/uiuserinterfacestyle) key in your app **Info.plist**. Use `Automatic` to support both light and dark modes. --- ### Supported appearance styles The `userInterfaceStyle` property supports the following values: - `automatic`: Follow system appearance settings and notify about any change the user makes. - `light`: Restrict the app to support light theme only. - `dark`: Restrict the app to support dark theme only. ## Detect the color scheme To detect the color scheme in your project, use `Appearance` or `useColorScheme` from `react-native`: ```tsx app/index.tsx import { Appearance, useColorScheme } from 'react-native'; ``` Then, you can use `useColorScheme()` hook as shown below: ```tsx app/index.tsx function MyComponent() { let colorScheme = useColorScheme(); if (colorScheme === 'dark') { // render some dark thing } else { // render some light thing } } ``` In some cases, you will find it helpful to get the current color scheme imperatively with [`Appearance.getColorScheme()` or listen to changes with `Appearance.addChangeListener()`](https://rn.nodejs.cn/docs/appearance). ## Additional information ### Minimal example #### useColorScheme example ```tsx import { StatusBar } from 'expo-status-bar'; export default function App() { const colorScheme = useColorScheme(); const themeTextStyle = colorScheme === 'light' ? styles.lightThemeText : styles.darkThemeText; const themeContainerStyle = colorScheme === 'light' ? styles.lightContainer : styles.darkContainer; return ( Color scheme: {colorScheme} ); } const styles = StyleSheet.create({ container: { flex: 1, alignItems: 'center', justifyContent: 'center', }, text: { fontSize: 20, }, lightContainer: { backgroundColor: '#d0d0c0', }, darkContainer: { backgroundColor: '#242c40', }, lightThemeText: { color: '#242c40', }, darkThemeText: { color: '#d0d0c0', }, }); ``` ### Tips While you are developing your project, you can change your simulator's or device's appearance by using the following shortcuts: - If using an Android Emulator, you can run `adb shell "cmd uimode night yes"` to enable dark mode, and `adb shell "cmd uimode night no"` to disable dark mode. - If using a physical Android device or an Android Emulator, you can toggle the system dark mode setting in the device's settings. - If working with an iOS emulator locally, you can use the Cmd ⌘ + Shift + a 用于在亮夜间模式之间切换的快捷方式。 ¥shortcut to toggle between light and dark modes. ## 动画 了解如何集成 React Native 动画并将其用于你的 Expo 项目。 动画是增强和提供更好用户体验的好方法。在你的 Expo 项目中,你可以使用 React Native 中的 [动画 API](https://rn.nodejs.cn/docs/next/animations)。但是,如果你想使用性能更好的更高级动画,可以使用 [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/) 库。它提供了一个 API,可以简化创建流畅、强大且可维护的动画的过程。 ¥Animations are a great way to enhance and provide a better user experience. In your Expo projects, you can use the [Animated API](https://rn.nodejs.cn/docs/next/animations) from React Native. However, if you want to use more advanced animations with better performance, you can use the [`react-native-reanimated`](https://docs.swmansion.com/react-native-reanimated/) library. It provides an API that simplifies the process of creating smooth, powerful, and maintainable animations. ## 安装 ¥Installation 如果你使用 [这篇博文](/get-started/create-a-project/) 创建了项目,则可以跳过安装 `react-native-reanimated`。此库已安装。否则,请通过运行以下命令进行安装: ¥You can skip installing `react-native-reanimated` if you have created a project using [the default template](/get-started/create-a-project/). This library is already installed. Otherwise, install it by running the following command: ```sh $ npx expo install react-native-reanimated ``` ## 用法 ¥Usage ### 最小的例子 ¥Minimal example 下面的例子展示了如何使用 `react-native-reanimated` 库创建一个简单的动画。有关 API 和高级用法的更多信息,请参阅 [`react-native-reanimated` 文档](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/your-first-animation)。 ¥The following example shows how to use the `react-native-reanimated` library to create a simple animation. For more information on the API and advanced usage, see [`react-native-reanimated` documentation](https://docs.swmansion.com/react-native-reanimated/docs/fundamentals/your-first-animation). #### Using react-native-reanimated ```tsx import Animated, { useSharedValue, withTiming, useAnimatedStyle, Easing, } from 'react-native-reanimated'; import { View, Button, StyleSheet } from 'react-native'; export default function AnimatedStyleUpdateExample() { const randomWidth = useSharedValue(10); const config = { duration: 500, easing: Easing.bezier(0.5, 0.01, 0, 1), }; const style = useAnimatedStyle(() => { return { width: withTiming(randomWidth.value, config), }; }); return (