React Native从入门到实战--常用导航器之堆栈导航器、底部导航器、顶部导航器、切换导航器、抽屉导航器
在上一次https://www.cnblogs.com/webor2006/p/14733646.html咱们对react-navigation导航器进行了一个基础的认识,而它本身又是一个比较复杂又常用的组件,所以这次专门来对它进行一个整体的学习,为下一次项目的启动做准备。
堆栈导航器:
效果:
使用堆栈导航器主要是实现如下几个场景,也是最基础的一个导航器:
1、页面跳转:
其中包含页面之间的传值。
2、页面内容与导航栏之间的交互:
另外还有就是,标题栏与内容区域的交互问题,如下:
其中在内容输入文本中输入内容时,会能反馈到标题上,而在标题上操作时,也能将其状态反馈到内容区域上。
实现:
先准备多个页面:
既然要实现页面之间的跳转,首先先准备几个测试页面,工程是基于上一次的,如下:
里面的内容很简单:
import React from "react"; import { StyleSheet, Text, View } from "react-native"; export default class Page1 extends React.Component { render() { return <View style={{ flex: 1, backgroundColor: "gray", paddingTop: 30 }}> <Text style={styles.text}>欢迎来到Page1</Text> </View>; } } const styles = StyleSheet.create({ text: { fontsize: 20, color: "white", }, });
如果对这块的代码还是有些模糊的话,可以先复习一下基础,这就是一个React的基础页面,接下来再增加一个返回上一页的操作按钮:
然后再准备一个按钮,用来跳转其它页面:
好,可以以此为模板,快速再造几个页面:
接下来再来准备一个入口首页面:
创建堆栈导航器:
对于这些个页面,运行app时首先展示哪个页面呢?此时就需要用到导航器了,由于下面还有几个导航器需要学习,所以为了统一管理,将其都放到一个新目录中,如下:
接下来则来创建堆栈导航器:
另外它还可有配置第二个参数,不过这里暂且只是先了解一下,先不配置:
比如说可以通过这个全局配置对所有页面的标题栏给隐藏,这个待用到时再说。
使用导航器:
接下来将咱们创建的导航器给使用一下,如下:
这样就可以将导航器转换为页面的元素了,之后使用导航器就跟使用正常的页面一样。
运行:
接下来咱们运行看一下效果,发现报错了:
其实是少了一个库,这里执行一下这个命令:"yarn add react-native-safe-area-context":
然后注意,此时需要进入到ios目录,执行一下“pod install”:
然后再运行,发现又报另一个错了。。
笔误:
其它界面可以都改一下,再运行就正常啦,如下:
定义标题:
其中可以看到,在ios中,在中转到子页面时,在返回按钮处会显示上一个页面的title:
那如果想自定义这个文案呢?可以这样:
这是对所有页面都生效的,那,如果某个页面想单独定义,可以这样在具体的页面这样定义:
此时再运行看一下:
其实还有一种设置方法,就是在创建导航器那块进行设置:
另外还可以给具体的页面设置一个标题,方式也跟返回标题文案一样,增加一个属性既可:
运行:
动态设置navigationOptions:
另外,还可以在跳转时通过传递动态的参数,来进行navigationOptions属性的设置,这里还是以设置页面标题为例:
接下来,在这块可以接收这个参数:
然后接收在这块:
运行:
页面内容与导航栏之间的交互:
如上面效果所示,接下来完成相关的效果,这也是实际项目中非常常见的一种场景。
1、右上角增加一个操作按钮:
运行,发现报错了,也是一个非常经典的错:ReferenceError: Can't find variable: React
少了一个import:
运行看一下:
2、增加点击事件:
当点击保存时,这里则会有两个状态,如下:
运行:
其中有个细节就是:
3、根据点击的状态,实时反馈在页面上,实现两者的初步交互:
接下来进行一次交互,就是把点击的状态反应在页面上,所以,先到页面中定义一个文件控件展示状态信息:
运行:
4、页面进行编辑,将状态反馈到标题栏上:
接下来将操作的主体变换一下,变成对页面进行操作,然后再将操作的状态反馈到标题上面,先在页面中声明一下文件输入框:
其中在导航器那块也进行相关的修改:
再运行:
全局的导航器配置:
最后,这里再来对导航器的全局配置作一个了解,也就是它:
如之前也已经使用过一回了,在这里面的配置是针对所有导航器的页面有效的,比如我们要隐藏所有页面的标题栏,可以这样配置:
那如果只想针对某个页面来进行设置,则就在具体的页面中设置属性既可:
底部导航器:
效果:
接下来再来学习另一种导航器,底部Tab效果,应该人人都见过:
其中在页面中也可以通过程序来动态切换指定的Tab:
实现:
导入底部导航器:
配置路由信息:
这里先来配置一个Tab:
具体配置如下:
然后使用一下:
运行,发现报错了:
此时在项目依赖包中可以看到:
记得执行一下"pod install":
再来编译一下,运行一下就可以了【注意:不要用reload的方式,需要重新使用npx react-native run-ios运行一下】:
接下来再来配置另一个Tab:
运行:
更改tab的风格:
更改tab选中的颜色:
更改tab非选中的颜色:
可以这样设置:
通过代码来跳转到指定Tab:
其实很简单,就是直接用路由跳转既可:
顶部导航器:
效果:
接着另一个常用的导航器就是顶部tab效果,如下:
实现:
配置顶部导航器:
跟底部导航器类似,配置如下:
const MaterialTopTabNavigator = createMaterialTopTabNavigator( { //在这里配置页面路由信息 Page1: { screen: Page1, navigationOptions: { tabBarLabel: "Page1", tabBarIcon: ({ tintColor, focused }) => ( <Ionicons name={"ios-home"} size={26} style={{ color: tintColor }} /> ), }, }, Page2: { screen: Page2, navigationOptions: { tabBarLabel: ({ tintColor, focused }) => (//自定义tab文字 <Text size={26} style={{ color: focused ? "orange" : "grey" }}>Page2</Text> ), tabBarIcon: ({ tintColor, focused }) => ( <Ionicons name={"ios-people"} size={26} style={{ color: focused ? "orange" : "grey" }} /> ), }, }, Page3: { screen: Page3, navigationOptions: { tabBarLabel: ({ tintColor, focused }) => (//自定义tab文字 <Text size={26} style={{ color: focused ? "orange" : "grey" }}>Page2</Text> ), tabBarIcon: ({ tintColor, focused }) => ( <Ionicons name={"ios-people"} size={26} style={{ color: focused ? "orange" : "grey" }} /> ), }, }, }, { tabBarOptions: { activeTintColor: "red", }, }, );
然后在堆栈导航器路由信息处,这样配置:
然后将顶部和底部导航器都配置到HomePage中:
运行:
定义样式:
然后效果如下:
而对于顶部导航器中的图标是不支持的,所以咱们可以将图标的设置给去掉:
切换导航器:
接下来再来学习另一个导航器,就是从A页面切到B页面,但是B页面是不能返回到A页面的,这个通常在APP登录页面时会有此需求,也就是通常登录之后进入首页了,首页是不会让用户返回到登录页的,
新建导航器文件:
准备一个登录页面:
配置导航器:
import { createStackNavigator } from "react-navigation-stack"; import HomePage from "../pages/HomePage"; import Page1 from "../pages/Page1"; import Login from "../pages/Login"; //登录之后的导航器 const AppStack = createStackNavigator( { Home: { screen: HomePage, }, Page1: { screen: Page1, }, }, ); //登录导航器 const AuthStack = createStackNavigator( { Login: { screen: Login, }, }, );
其中登录之后跳到HomePage时,里面可以跳转到Page1,修改一下页面代码:
好,配置了两个导航器怎么用呢?此时就可以使用到这个切换导航器了,如下:
其中在之前登录页面中点击按钮已经设置跳转到首页了:
最后,别忘了在这块配置咱们的这个切换导航器:
运行:
可以看到,确实是在首页就无法再返回到登录页面了。
另外最后,有一个细节需要说明一下:
其实是两种写法,也可以如下定义:
抽屉导航器:
效果:
侧拉抽屉效果也是APP中常用的一种布局方式,如下:
实现:
准备page4、page5页面:
这里在侧滑列表中会用到另外两个页面,先准备好:
配置导航器:
其中侧拉的每一项有一个图标和文字:
可以这样配置:
将各种导航器汇集到HomePage中:
为了便于以后的复习,将所有学到的导航器都弄汇集到一起,具体如下:
然后在HomePage中来调用一下:
最后还得修改一下它:
运行:
发现报错了。。
网上搜了一下,在这个帖子找到相关的解决方案:https://github.com/react-navigation/react-navigation/issues/9665,
我目前使用的是高于它的:
所以咱们将版本降低到2.1.0试一下:
此时确保版本为:
此时再运行,发现好使了,如果发现运行还是不好使,最后往下翻贴子,发现了新大路,就是它:
执行完它之后,再运行就正常了,效果如下:
说实话,RN的坑真的是无处不在呀~~
调用抽屉常用API:
接下来回到页面中,进行抽屉行为的控制,如打开与关闭抽屉,常用的抽屉API有:
具体来使用一下:
此时运行一下:
自定义侧拉栏选项卡:
对于展开的侧拉栏,咱们也可以进行自定义,首先需要导入一些组件:
1、SafeAreaView:
在导航器中会使用它来适配刘海屏。
2、ScrollView:
当侧拉选项过多时,需要可以上下滚动,所以需要导入它:
3、DrawerNavigatorItems:
接下来再来导入它:
4、开始DIY:
接下来则来配置一下,先来改变一下整体的背景色:
运行看一下:
其中对于每一个顶DrawerNavigatorItems也可以样式自定义设置的,这里就看一下它的相关属性,不演示了:
另外,还可以针对所有侧边项进行全局的配置,比如目前菜单选中是样式看不太清:
这里将选中时的图标和文字变成白色,如下:
此时的效果:
在Android上运行:
最后,咱们再看一下在Android上运行的效果,先将服务启动“react-native start”,然后再执行“npx react-native run-android”,发现报错了。。
主是因为咱们使用到了react-native-screens:
它应该是有gradle版本的要求,那此时咱们需要到android目录中改一下gradle的版本为:
此时是不是可以看出,要想RN学得好,其实你要是能对Native平台有相关了解会更加妥,因为有时候是需要修改native的东东的,好,当你修改了gradle版本之后,有一个非常要注意的地方来了:
为啥?因为有可能有缓存干扰你运行【有时候会遇到安装不上的问题,反正各种诡异情况出现时,第一时间想到它】,咱们再来运行看一下,可能你会遇到这种错误:
(base) xiongweideMacBook-Pro:react_navigation_demo xiongwei$ npx react-native run-android info Running jetifier to migrate libraries to AndroidX. You can disable it using "--no-jetifier" flag. Jetifier found 1101 file(s) to forward-jetify. Using 4 workers... info Starting JS server... info Installing the app... > Task :app:installDebug FAILED 02:53:22 V/ddms: execute: running am get-config 02:53:22 V/ddms: execute 'am get-config' on '4ee36565' : EOF hit. Read: -1 02:53:22 V/ddms: execute: returning Installing APK 'app-debug.apk' on 'Redmi Note 7 - 9' for app:debug 02:53:22 D/app-debug.apk: Uploading app-debug.apk onto device '4ee36565' 02:53:22 D/Device: Uploading file onto device '4ee36565' 02:53:22 D/ddms: Reading file permision of /Users/xiongwei/Documents/workspace/reactnativestudy/reactive-native-study/react_navigation_demo/android/app/build/outputs/apk/debug/app-debug.apk as: rw-r--r-- 02:53:23 V/ddms: execute: running pm install -r -t "/data/local/tmp/app-debug.apk" 02:53:23 V/ddms: execute 'pm install -r -t "/data/local/tmp/app-debug.apk"' on '4ee36565' : EOF hit. Read: -1 02:53:23 V/ddms: execute: returning Deprecated Gradle features were used in this build, making it incompatible with Gradle 7.0. Use '--warning-mode all' to show the individual deprecation warnings. See https://docs.gradle.org/6.1.1/userguide/command_line_interface.html#sec:command_line_warnings 129 actionable tasks: 2 executed, 127 up-to-date Unable to install /Users/xiongwei/Documents/workspace/reactnativestudy/reactive-native-study/react_navigation_demo/android/app/build/outputs/apk/debug/app-debug.apk com.android.ddmlib.InstallException: Unknown failure: Error: Failed to parse APK file: /data/local/tmp/app-debug.apk Exception occurred while executing: java.lang.IllegalArgumentException: Error: Failed to parse APK file: /data/local/tmp/app-debug.apk at com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:338) at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:906) at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:158) at android.os.ShellCommand.exec(ShellCommand.java:103) at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21933) at android.os.Binder.shellCommand(Binder.java:634) at android.os.Binder.onTransact(Binder.java:532) at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2809) at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:4023) at android.os.Binder.execTransact(Binder.java:735) Caused by: android.content.pm.PackageParser$PackageParserException: Failed to parse /data/local/tmp/app-debug.apk at android.content.pm.PackageParser.parseApkLiteInner(PackageParser.java:1612) at android.content.pm.PackageParser.parseApkLite(PackageParser.java:1570) at com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:331) ... 9 more Caused by: java.io.FileNotFoundException: AndroidManifest.xml at android.content.res.ApkAssets.nativeOpenXml(Native Method) at android.content.res.ApkAssets.openXml(ApkAssets.java:152) at android.content.pm.PackageParser.parseApkLiteInner(PackageParser.java:1589) ... 11 more at com.android.ddmlib.Device.installRemotePackage(Device.java:1133) at com.android.ddmlib.Device.installPackage(Device.java:963) at com.android.ddmlib.Device.installPackage(Device.java:939) at com.android.ddmlib.Device.installPackage(Device.java:928) at com.android.builder.testing.ConnectedDevice.installPackage(ConnectedDevice.java:126) at com.android.build.gradle.internal.tasks.InstallVariantTask.install(InstallVariantTask.java:175) at com.android.build.gradle.internal.tasks.InstallVariantTask.doTaskAction(InstallVariantTask.java:106) at com.android.build.gradle.internal.tasks.NonIncrementalTask$taskAction$$inlined$recordTaskAction$1.invoke(AndroidVariantTask.kt:51) at com.android.build.gradle.internal.tasks.NonIncrementalTask$taskAction$$inlined$recordTaskAction$1.invoke(AndroidVariantTask.kt:31) at com.android.build.gradle.internal.tasks.Blocks.recordSpan(Blocks.java:91) at com.android.build.gradle.internal.tasks.NonIncrementalTask.taskAction(NonIncrementalTask.kt:34) at sun.reflect.GeneratedMethodAccessor75.invoke(Unknown Source) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at org.gradle.internal.reflect.JavaMethod.invoke(JavaMethod.java:104) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.doExecute(StandardTaskAction.java:49) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:42) at org.gradle.api.internal.project.taskfactory.StandardTaskAction.execute(StandardTaskAction.java:28) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:727) at org.gradle.api.internal.AbstractTask$TaskActionWrapper.execute(AbstractTask.java:694) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$3.run(ExecuteActionsTaskExecuter.java:568) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:402) at org.gradle.internal.operations.DefaultBuildOperationExecutor$RunnableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:394) at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158) at org.gradle.internal.operations.DefaultBuildOperationExecutor.run(DefaultBuildOperationExecutor.java:92) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.run(DelegatingBuildOperationExecutor.java:31) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeAction(ExecuteActionsTaskExecuter.java:553) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeActions(ExecuteActionsTaskExecuter.java:536) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.access$300(ExecuteActionsTaskExecuter.java:109) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.executeWithPreviousOutputFiles(ExecuteActionsTaskExecuter.java:276) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter$TaskExecution.execute(ExecuteActionsTaskExecuter.java:265) at org.gradle.internal.execution.steps.ExecuteStep.lambda$execute$1(ExecuteStep.java:33) at java.util.Optional.orElseGet(Optional.java:267) at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:33) at org.gradle.internal.execution.steps.ExecuteStep.execute(ExecuteStep.java:26) at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:63) at org.gradle.internal.execution.steps.CleanupOutputsStep.execute(CleanupOutputsStep.java:35) at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:49) at org.gradle.internal.execution.steps.ResolveInputChangesStep.execute(ResolveInputChangesStep.java:34) at org.gradle.internal.execution.steps.CancelExecutionStep.execute(CancelExecutionStep.java:43) at org.gradle.internal.execution.steps.TimeoutStep.executeWithoutTimeout(TimeoutStep.java:73) at org.gradle.internal.execution.steps.TimeoutStep.execute(TimeoutStep.java:54) at org.gradle.internal.execution.steps.CatchExceptionStep.execute(CatchExceptionStep.java:34) at org.gradle.internal.execution.steps.CreateOutputsStep.execute(CreateOutputsStep.java:44) at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:54) at org.gradle.internal.execution.steps.SnapshotOutputsStep.execute(SnapshotOutputsStep.java:38) at org.gradle.internal.execution.steps.BroadcastChangingOutputsStep.execute(BroadcastChangingOutputsStep.java:49) at org.gradle.internal.execution.steps.CacheStep.executeWithoutCache(CacheStep.java:153) at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:67) at org.gradle.internal.execution.steps.CacheStep.execute(CacheStep.java:41) at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:44) at org.gradle.internal.execution.steps.StoreExecutionStateStep.execute(StoreExecutionStateStep.java:33) at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:38) at org.gradle.internal.execution.steps.RecordOutputsStep.execute(RecordOutputsStep.java:24) at org.gradle.internal.execution.steps.SkipUpToDateStep.executeBecause(SkipUpToDateStep.java:92) at org.gradle.internal.execution.steps.SkipUpToDateStep.lambda$execute$0(SkipUpToDateStep.java:85) at java.util.Optional.map(Optional.java:215) at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:55) at org.gradle.internal.execution.steps.SkipUpToDateStep.execute(SkipUpToDateStep.java:39) at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:76) at org.gradle.internal.execution.steps.ResolveChangesStep.execute(ResolveChangesStep.java:37) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:36) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsFinishedStep.execute(MarkSnapshottingInputsFinishedStep.java:26) at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:94) at org.gradle.internal.execution.steps.ResolveCachingStateStep.execute(ResolveCachingStateStep.java:49) at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:79) at org.gradle.internal.execution.steps.CaptureStateBeforeExecutionStep.execute(CaptureStateBeforeExecutionStep.java:53) at org.gradle.internal.execution.steps.ValidateStep.execute(ValidateStep.java:74) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.lambda$execute$2(SkipEmptyWorkStep.java:78) at java.util.Optional.orElseGet(Optional.java:267) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:78) at org.gradle.internal.execution.steps.SkipEmptyWorkStep.execute(SkipEmptyWorkStep.java:34) at org.gradle.internal.execution.steps.legacy.MarkSnapshottingInputsStartedStep.execute(MarkSnapshottingInputsStartedStep.java:39) at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:40) at org.gradle.internal.execution.steps.LoadExecutionStateStep.execute(LoadExecutionStateStep.java:28) at org.gradle.internal.execution.impl.DefaultWorkExecutor.execute(DefaultWorkExecutor.java:33) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.executeIfValid(ExecuteActionsTaskExecuter.java:192) at org.gradle.api.internal.tasks.execution.ExecuteActionsTaskExecuter.execute(ExecuteActionsTaskExecuter.java:184) at org.gradle.api.internal.tasks.execution.CleanupStaleOutputsExecuter.execute(CleanupStaleOutputsExecuter.java:109) at org.gradle.api.internal.tasks.execution.FinalizePropertiesTaskExecuter.execute(FinalizePropertiesTaskExecuter.java:46) at org.gradle.api.internal.tasks.execution.ResolveTaskExecutionModeExecuter.execute(ResolveTaskExecutionModeExecuter.java:62) at org.gradle.api.internal.tasks.execution.SkipTaskWithNoActionsExecuter.execute(SkipTaskWithNoActionsExecuter.java:57) at org.gradle.api.internal.tasks.execution.SkipOnlyIfTaskExecuter.execute(SkipOnlyIfTaskExecuter.java:56) at org.gradle.api.internal.tasks.execution.CatchExceptionTaskExecuter.execute(CatchExceptionTaskExecuter.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.executeTask(EventFiringTaskExecuter.java:77) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:55) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter$1.call(EventFiringTaskExecuter.java:52) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:416) at org.gradle.internal.operations.DefaultBuildOperationExecutor$CallableBuildOperationWorker.execute(DefaultBuildOperationExecutor.java:406) at org.gradle.internal.operations.DefaultBuildOperationExecutor$1.execute(DefaultBuildOperationExecutor.java:165) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:250) at org.gradle.internal.operations.DefaultBuildOperationExecutor.execute(DefaultBuildOperationExecutor.java:158) at org.gradle.internal.operations.DefaultBuildOperationExecutor.call(DefaultBuildOperationExecutor.java:102) at org.gradle.internal.operations.DelegatingBuildOperationExecutor.call(DelegatingBuildOperationExecutor.java:36) at org.gradle.api.internal.tasks.execution.EventFiringTaskExecuter.execute(EventFiringTaskExecuter.java:52) at org.gradle.execution.plan.LocalTaskNodeExecutor.execute(LocalTaskNodeExecutor.java:41) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:372) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$InvokeNodeExecutorsAction.execute(DefaultTaskExecutionGraph.java:359) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:352) at org.gradle.execution.taskgraph.DefaultTaskExecutionGraph$BuildOperationAwareExecutionAction.execute(DefaultTaskExecutionGraph.java:338) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.lambda$run$0(DefaultPlanExecutor.java:127) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.execute(DefaultPlanExecutor.java:191) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.executeNextNode(DefaultPlanExecutor.java:182) at org.gradle.execution.plan.DefaultPlanExecutor$ExecutorWorker.run(DefaultPlanExecutor.java:124) at org.gradle.internal.concurrent.ExecutorPolicy$CatchAndRecordFailures.onExecute(ExecutorPolicy.java:64) at org.gradle.internal.concurrent.ManagedExecutorImpl$1.run(ManagedExecutorImpl.java:48) at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) at org.gradle.internal.concurrent.ThreadFactoryImpl$ManagedThreadRunnable.run(ThreadFactoryImpl.java:56) at java.lang.Thread.run(Thread.java:748) FAILURE: Build failed with an exception. * What went wrong: Execution failed for task ':app:installDebug'. > com.android.builder.testing.api.DeviceException: com.android.ddmlib.InstallException: Unknown failure: Error: Failed to parse APK file: /data/local/tmp/app-debug.apk Exception occurred while executing: java.lang.IllegalArgumentException: Error: Failed to parse APK file: /data/local/tmp/app-debug.apk at com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:338) at com.android.server.pm.PackageManagerShellCommand.runInstall(PackageManagerShellCommand.java:906) at com.android.server.pm.PackageManagerShellCommand.onCommand(PackageManagerShellCommand.java:158) at android.os.ShellCommand.exec(ShellCommand.java:103) at com.android.server.pm.PackageManagerService.onShellCommand(PackageManagerService.java:21933) at android.os.Binder.shellCommand(Binder.java:634) at android.os.Binder.onTransact(Binder.java:532) at android.content.pm.IPackageManager$Stub.onTransact(IPackageManager.java:2809) at com.android.server.pm.PackageManagerService.onTransact(PackageManagerService.java:4023) at android.os.Binder.execTransact(Binder.java:735) Caused by: android.content.pm.PackageParser$PackageParserException: Failed to parse /data/local/tmp/app-debug.apk at android.content.pm.PackageParser.parseApkLiteInner(PackageParser.java:1612) at android.content.pm.PackageParser.parseApkLite(PackageParser.java:1570) at com.android.server.pm.PackageManagerShellCommand.setParamsSize(PackageManagerShellCommand.java:331) ... 9 more Caused by: java.io.FileNotFoundException: AndroidManifest.xml at android.content.res.ApkAssets.nativeOpenXml(Native Method) at android.content.res.ApkAssets.openXml(ApkAssets.java:152) at android.content.pm.PackageParser.parseApkLiteInner(PackageParser.java:1589) ... 11 more * Try: Run with --stacktrace option to get the stack trace. Run with --info or --debug option to get more log output. Run with --scan to get full insights. * Get more help at https://help.gradle.org BUILD FAILED in 7s error Failed to install the app. Make sure you have the Android development environment set up: https://reactnative.dev/docs/environment-setup. Run CLI with --verbose flag for more details. Error: Command failed: ./gradlew app:installDebug -PreactNativeDevServerPort=8081 Unable to install /Users/xiongwei/Documents/workspace/reactnativestudy/reactive-native-study/react_navigation_demo/android/app/build/outputs/apk/debug/app-debug.apk
这时可以把这俩目录都给删掉:
再来编译运行一下貌似就好了,整体效果如下:
效果还是不错的。
总结:
至此,我们对于常用的导航器有了一定的了解了,在下一次则正式进入到项目开发来综合操练RN的知识了,有了之前扎实的基础,之后项目的学习也会变得比较踏实。