React Native从入门到实战--高性能列表组件SectionList详解、react-navigation、矢量图标
高性能列表组件SectionList详解:
前言:
在上一次https://www.cnblogs.com/webor2006/p/14716461.html咱们对于高性能的VirtualizedList的列表组件进行了初步学习,其中对于列表组件回忆一下当时谈到了三种:
其中对于FlatList已经学习过了,接下来则来学习一下SectionList。
SectionList是一个基于VirtualizedList高性能的分组(section)列表组件,支持下面这些常用的功能:
- 完全跨平台。
- 支持水平布局模式。
- 行组件显示或隐藏时可配置回调事件。
- 支持单独的头部组件。
- 支持单独的尾部组件。
- 支持自定义行间分隔线。
- 支持下拉刷新。
- 支持上拉加载。
上面这些貌似都是FlatList的特点。。而它和FlatList不同之处在于它支持分组(section)列表的功能:
所以,如果你的列表中不需要分组(section)效果,那么就可以使用更简单的FlatList。
理论了解:
简单用例:
其中renderItem跟FlatList一样,必须的列表条目,而renderSectionHeader则是SectionList显示头部特有的,其中对于sections的数据格式可以看到,每一个title对应一个数组的data,表示每个分组对应的多个item。
属性:
接下来则先来对此组件的一些常用属性进行一个简单认识。
属性1:
用来渲染的数据,类似于中FlatList中的data属性,一般格式为:
属性2:
用来渲染每一个section中的每一个列表项的默认渲染器。可以在section级别上进行覆盖重写。
属性3:
在每个section的头部渲染,在ios上,这些headers是默认粘接在ScrollView的顶部的,参见stickySectionHeadersEnabled.
属性4:
在等待加载新数据时将此属性设为true,列表就会显示出一个正在加载的符号。
属性5:
如果设置了此选项。则会在列表头部添加一个标准的RefreshControl控件,以便实现“下拉刷新”的功能。同时你需要正确设置refreshing属性。
属性6:
当下一次section把它的前一个section的可视区推离屏幕的时候,让这个section的header粘连在屏幕的顶端。这个属性在IOS上是默认可用的,因为这是IOS的平台规范。
属性7:
行与行之间的分隔线组件。不会出现在第一行之前和最后一行之后。
属性8:
通过它设置尾部组件。
属性9:
通过它设置头部组件。
属性10:
当列表为空时渲染,可以是一个React组件类,一个渲染函数,或一个已经渲染的元素。
属性11:
在每个section的顶部和底部渲染(区别于ItemSeparatorComponent,它仅在列表项之间渲染)。它的作用是为了从视觉上把section与它上方或下方的headers区别开来,从这个意义上讲,它的作用和ItemSeparatorComponent是一样的,它也接受highlighted,[leading/trailing][Item/Separator]这两个默认提供的属性或其他通过separators.updateProps添加的自定义属性。
属性12:
如果有除data以外的数据用在列表中(不论是用在renderItem还是Header或者Footer中),请在此属性中指定。同时此数据在修改时也需要先修改其引用地址(比如先复制到一个新的Object或者数组中),然后再修改其值,否则界面很可能不会刷新。
属性13:
指定一开始渲染的元素数量,最好刚刚够填满一个屏幕,这样保证了用最短的时间给用户呈现可见的内容。注意这第一批次渲染的元素不会在滑动过程中被卸载,这样是为了保证用户执行返回顶部的操作时,不需要重新渲染首批元素。
属性14:
翻转滚动方向。实质是将scale变换设置为-1。
属性15:
此函数用于给定的item生成一个不重复的key。Key的作用是使React能够区分同类元素的不同个体,以便在刷新时能够确定其变化的位置,减少重新渲染的开销。若不指定此函数,则默认抽取item.key作为key值。若item.key也不存在,则使用数组下标。
属性16:
当列表被滚动到距离内容最底部不足onEndReachedThreshold的距离时调用。
属性17:
决定当距离内容最底部还有多远时触发onEndReached回调。注意此参数是一个比值而非像素单位。比如,0.5表示距离内容最底部的距离为当前列表可见长度的一半时触发。
方法:
方法1:
将可视区内位于特定sectionIndex或itemIndex(section内)位置的列表项,滚动到可视区的特定位置。比如说,viewPosition为0时将这个列表项滚动到可视区顶部(可能会被顶部粘接的headers覆盖),为1时将它滚动到可视区底部,为0.5时将它滚动到可视区中央。viewOffset是一个以像素为单位,到最终位置偏移距离的固定值,比如为了弥补粘接的header所占据的空间。
注意:如果没有设置getItemLayout,就不能滚动到位于外部渲染区的位置 。
方法2:
主动通知列表发生了一个事件,以使列表重新计算可视区域。比如说当waitForInteractions为true并且用户没有滚动列表时,就可以调用这个方法,不过一般来说,当用户点击了一个列表项,或发生了一个导航动作时,我们就可以调用这个方法。
方法3:
短暂地显示滚动指示器。
具体实践:
效果:
实现:
1、先运行一个项目,确保环境木问题:
由于好长一段时间木有学RN了,所以先运行确保一下环境木有问题:
然后运行时,果真出问题了:
TaskQueue: Error with task: undefined is not an object (evaluating '_this.view._component.measureInWindow') in react native
StackOverflow上搜了一下解决方案:https://stackoverflow.com/questions/60944091/taskqueue-error-with-task-undefined-is-not-an-object-evaluating-this-view,其中说到2种解决方案:
一种是将react-navigation版本升到5.x,先看一下咱们目前用的版本:
用的是一个超老的版本,但是呢如果升级的话可能比较麻烦,为了不影响学习这里还是使用该版本,于是采用贴子中说的第二点方案,先找到这个文件:
此时再运行就对了,但是此时会提示这么一个警告。。
也就是getNode()是不需要了,其实在贴子中有人已经给出相关评论了:
所以,此时将getNode()去掉了:
再运行就没报这种警告了,只是还有其它警告,这里先忽略了,先往前学着:
1、新建页面,添加测试入口:
由于跟FlatList用法差不多,直接基于它拷贝一个新页面:
然后增加一个跳转到此页面的测试入口:
然后在App.js中增加一个测试按钮:
此时运行看一下:
2、准备数据源:
此时运行看一下效果:
此时的效果跟FlatList木有啥区别,因为还有属性没有设置。
3、设置分组标题:renderSectionHeader:
如上面属性介绍:
所以来设置一下:
其中涉及到一个样式:
运行发现在android和ios上的表现是有些差别的,先来看ios的效果:
其中可以看到有一个悬浮的效果,但是呢到了android上面就没有悬浮了:
这可能是平台的差异吧,目前每个Item太高了,这里将其margin取消掉之后再运行一下:
此时再看一下效果:
4、设置分隔线:
先来改一下item的背景色为白色,设置的目的是为了暴露分隔线问题:
此时的效果如下:
是不是item与item差了分隔线了,所以接下来设置一下,如之前属性所示:
此时看效果:
5、下拉刷新处理:
接下来处理下拉刷新逻辑,首先将数据源写活,目前我们是写死成了静态数据了:
改成:
如果你觉得在访问state中的数据时每次都需要用"this.state.xxx"来访问比较麻烦,此时解构的场景就出来了,也是经常会用到的一个小技巧,如下:
运行:
其中为啥下拉刷新之后会显示这些数据,这里简单再回忆一下上次写的加载的逻辑:
以上就是SectionList的基本用法,一些其它用法可以之后再慢慢挖掘。
react-navigation:
了解前世今生:
概述:
还记得我们入口页面的导航用的是哪个组件么,瞅一下我们的代码:
是的,react-navigation导航器组件,接下来则来对它进行一个整体的认识:导航器是做APP开发所不可或缺的一个组件,现在RN生态中最主流的导航器当react-navigation莫属了。RN发展初期有个名叫Navigator的导航器,但因为其功能单一,RN社区便开始组织构建了一个功能更强大的导航器便是react-navigation了,随着react-navigation逐渐稳定,Navigator也被光荣的退休了。
react-navigation的出现替代了Navigator、Ex-Navigation等老一代的导航组件,react-navigation可以说是Navigator的加强版,不仅有Navigator的全部功能,另外还支持底部导航类似于与IOS中的UiTabBarController,此外它也支持侧拉效果方式的导航类似于Android中的抽屉效果。
react-navigation发展到现在已经经历了1x,2x,3x,4x,5x【目前5x先不关注,先跟着教程的节奏】的版本,目前使用不同版本react-navigation的开发者都有,了解react-navigation不同版本的差异和功能有助于我们进行导航器的开发和应用。
各react-navigation版本的差异:
看一下咱们目前使用的版本:
。。老古董了,所以正好借此机会对它有一个整体的了解,以便为以后升级做准备。
在了解了各版本的差异之外,接下来则来了解一下什么是导航器以及它们的通用API,依然照着大神的这篇https://www.devio.org/2018/12/15/react-navigation3x/来过一遍【过一遍的作用是强制让他人的知识点为自己所用】。
什么是导航器?
导航器可以看成是一个普通的React组件,你可以通过导航器来定义你的APP的导航结构。导航器还可以渲染通用元素,例如可以配置的标题栏和选项卡栏。
在react-navigation中常用的导航器有以下7种【可能现在要多于它,但是不管这么多,先保持跟学习教程的一个同步节奏,学习节奏还是很重要的】:
- createStackNavigator: 类似于普通的Navigator,屏幕上方导航栏;【最常用】
- createTabNavigator: createTabNavigator已弃用,使用createBottomTabNavigator和/或createMaterialTopTabNavigator替代;
- createBottomTabNavigator:相当于iOS里面的TabBarController,屏幕下方的标签栏;
- createMaterialTopTabNavigator:屏幕顶部的材料设计主题标签栏;
- createDrawerNavigator: 抽屉效果,侧边滑出;
- createSwitchNavigator:SwitchNavigator 的用途是一次只显示一个页面。
你可以通过以上7种导航器来创建你APP,可以是其中一个也可以多个组合,这个可以根据具体的应用场景并结合每一个导航器的特性进行选择。
在开始学习7种导航器之前,我们需要先了解两个和导航关于概念:
Screen navigation prop(屏幕导航属性)
:通过navigation可以完成屏幕之间的调度操作,例如打开另一个屏幕;Screen navigationOptions(屏幕导航选项)
: 通过navigationOptions可以定制导航器显示屏幕的方式(例如:头部标题,选项卡标签等);
简单使用示例:
const SomeNav = createStackNavigator/createBottomTabNavigator/createMaterialTopTabNavigator/createDrawerNavigator/createSwitchNavigator({ // config }); <SomeNav screenProps={xxx} ref={nav => { navigation = nav; }} onNavigationStateChange=(prevState, newState, action)=>{ } />
- ref:可以通过
ref
属性获取到navigation
; - onNavigationStateChange(prevState, newState, action):顶级节点除了
ref
属性之外,还接受onNavigationStateChange(prevState, newState, action)
属性,每次当导航器所管理的state
发生改变时,都会回调该方法;- prevState:变化之前的state;
- newState:新的state;
- 导致state变化的action;
- screenProps:向子屏幕传递额外的数据,子屏幕可以通过this.props.screenProps获取到该数据。
Screen Navigation Prop(屏幕的navigation Prop):
当导航器中的屏幕被打开时,它会收到一个navigation
prop,navigation
prop是整个导航环节的关键一员,接下来就详细讲解一下navigation
的作用。
navigation包含以下功能:
- navigate:跳转到其他界面;【咱们目前采用的就是它】
- state:屏幕的当前state;
- setParams:改变路由的params;
- goBack:关闭当前屏幕;
- dispatch:向路由发送一个action;
- addListener:订阅导航生命周期的更新;
- isFocused:true 标识屏幕获取了焦点;
- getParam:获取具有回退的特定参数;
- dangerouslyGetParent:返回父导航器;
其中看一下我们代码中的路由跳转就是利用的navigation:
注意:一个navigation有可能没有navigate、setParams以及goBack,只有state与dispatch,所以在使用navigate时要进行判断,如果没有navigate可以使用navigation去dispatch一个新的action。如:
const {navigation,theme,selectedTab}=this.props; const resetAction = StackActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'HomePage', params:{ theme:theme, selectedTab:selectedTab }, }) ] }) navigation.dispatch(resetAction)
提示:这里的reset
在2.0及以后版本中被从NavigationActions中移到了StackActions
中,使用时记得留意。
StackNavigator的navigation的额外功能:
当且仅当当前 navigator 是 stack navigator 时【在前面不是说了创建navigotor有很多方式,其实就有一个createStackNavigator,就是指这种场景】,this.props.navigation
上有一些附加功能。 这些函数是 navigate 和 goBack 的替代方法, 你可以使用任何你喜欢的方法。 这些功能是:
- this.props.navigation
push - 导航到堆栈中的一个新的路由
pop - 返回堆栈中的上一个页面
popToTop - 跳转到堆栈中最顶层的页面
replace - 用新路由替换当前路由
reset - 擦除导航器状态并将其替换为多个操作的结果
dismiss - 关闭当前栈
使用navigate进行界面之间的跳转:
在进行页面跳转时,我们会调用navigate方法对吧:
下面来学习一下它的用法:navigation.navigate({routeName, params, action, key})
或 navigation.navigate(routeName, params, action)
- routeName:要跳转到的界面的路由名,也就是在导航其中配置的路由名;
- params:要传递给下一个界面的参数;
- action:如果该界面是一个navigator的话,将运行这个sub-action;
- key:要导航到的路由的可选标识符。 如果已存在,将后退到此路由;
比如:
export const AppStackNavigator = createStackNavigator({ HomeScreen: { screen: HomeScreen }, Page1: { screen: Page1 }) class HomeScreen extends React.Component { render() { const {navigate} = this.props.navigation; return ( <View> <Text>This is HomeScreen</Text> <Button onPress={() => navigate('Page1', {name: 'Devio'})} title="Go to Page1" /> </View> ) } }
使用state的params:
在跳转路由的时候,不是可以携带参数么?比如上面的例子中的:
所以这里就来学习一下参数使用的问题,其实也很简单,可以通过this.props.state.params来获取通过setParams()
,或navigation.navigate()
传递的参数。比如:
此时在页面中接收参数则需要这么写:
需要一层层解构。
使用setParams 改变route params:
setParams: function setParams(params)
: 我们可以借助setParams
来改变route params,比如,通过setParams
来更新页面顶部的标题,返回按钮等;
注意:navigation.setParams改变的是当前页面的Params,如果要改变其他页面的Params可以通过NavigationActions.setParams完成,之后会学习到。
使用goBack返回到上一页面或指定页面:
goBack: function goBack(key)
:我们可以借助goBack
返回到上一页或者路由栈的指定页面。
- 其中
key
表示你要返回到页面的页面标识如id-1517035332238-4
,不是routeName。 - 可以通过指定页面的
navigation.state.key
来获得页面的标识。 - key非必传,也可传null,如果是返回上一页,此key可不传。
navigation.state {params: {…}, key: "id-1517035332238-4", routeName: "Page1"}
也就是说,我们可以通过navigation.state中来获取key值,如下:
export default class Page1 extends React.Component { render() { const {navigation} = this.props; return <View style=> <Text style={styles.text}>欢迎来到Page1</Text> <Button title="Go Back" onPress={() => { navigation.goBack(); }} /> </View> } }
通过dispatch发送一个action:
还记得上面说过这么一个东东么,回忆一下:
接下来就来了解这个dispatch:
dispatch: function dispatch(action)
:给当前界面设置action,会替换原来的跳转,回退等事件。
那都能发送哪些Action呢?下面就来瞅一下。
1、NavigationActions:
这个Actions涉及到如下API:
- Navigate : 导航到其他的页面;
- Back : 返回到上一个页面;
- Set Params : 设置指定页面的Params;
- Init : 初始化一个 state 如果 state 是 undefined;
下面具体来看一下这些api:
a、Navigate :
Navigatie action会使用Navigate action的结果来更新当前的state。
方法原型:navigate({routeName, params, action, key})
- routeName:字符串,必选项,在app的router里注册的导航目的地的routeName。
- params:对象,可选项,融合进目的地route的参数。
- action:对象,可选项(高级),如果screen也是一个navigator,次级action可以在子router中运行。在文档中描述的任何actions都可以作为次级action。
- key:
string or null
可选,要导航到的路由的标识符。如果已存在, 则导航回此路由。
import { NavigationActions } from 'react-navigation' const navigateAction = NavigationActions.navigate({ routeName: 'Profile', params: {}, action: NavigationActions.navigate({ routeName: 'SubProfileRoute'}) }) this.props.navigation.dispatch(navigateAction)
上面代码的意思是跳转到Profile页面,其参数为空,另外还有一个子action。
b、Back :
返回到前一个screen并且关闭当前screen.backaction creator接受一个可选的参数:
方法原型:back(key)
- key:
String
可选,这个可以和上文中讲到的goBack的key是一个概念;
import { NavigationActions } from 'react-navigation' const backAction = NavigationActions.back(); this.props.navigation.dispatch(backAction);
c、Set Params :
通过SetParams我们可以修改指定页面的Params。
- params:对象,必选参数,将会被合并到已经存在页面的Params中。
- key:字符串,必选参数,页面的key。
import { NavigationActions } from 'react-navigation' const setParamsAction = NavigationActions.setParams({ params: { title: 'HomePage' }, key: 'id-1517035332238-4', });
这里有一个小疑问:navigation中其实已经有setParams了为什么还要有NavigationActions.setParams呢?其实原因有两点:
- 在上文中讲到过navigation中有可能只有state与dispatch,这个时候如果要修改页面的Params,则只能通过
NavigationActions.setParams
了; - 另外,navigation.setParams只能修改当前页面的Params,而
NavigationActions.setParams
可以修改所有页面的Params;
2、StackActions:
该Actions有如下API:
- Reset : 重置当前 state 到一个新的state;
- Replace : 使用另一个路由替换指定的路由;
- Push : 在堆栈顶部添加一个页面,然后跳转到该页面;
- Pop : 跳转到上一个页面;
- PopToTop : 跳转到堆栈最顶层的页面,并销毁其他所有页面;
下面一一来看一下。
a、Reset:
Reset action删掉所有的navigation state并且使用这个actions的结果来代替。
- index,数组,必选,navigation state中route数组中激活route的index。
- actions,数组,必选项,Navigation Actions数组,将会替代navigation state。
- key:
string or null
可选, 如果设置,具有给定 key 的导航器将重置。 如果为null,则根导航器将重置。
import { NavigationActions, StackActions } from 'react-navigation' const resetAction = StackActions.reset({ index: 0, actions: [ NavigationActions.navigate({ routeName: 'Profile'}) ] }) this.props.navigation.dispatch(resetAction)
此代码的意思是恢复第0的navigation的状态,并且用Profile这个路由来代替。使用场景:比如app从Splash进入了首页,然后此时按back键是不想再回到了Splash页,这时可以使用NavigationActions.reset
重置它。
index参数被用来定制化当前激活的route。举个例子:使用两个routes WelcomePage和HomePage给一个基础的stack navigation设置。为了重置route到HomePage,但是在堆栈中又存放在WelcomePage之上,你可以这么做:
import { NavigationActions, StackActions } from 'react-navigation' const resetAction = StackActions.reset({ index: 1, actions: [ NavigationActions.navigate({ routeName: 'WelcomePage'}), NavigationActions.navigate({ routeName: 'HomePage'}) ] }); this.props.navigation.dispatch(resetAction);
说实话,目前还不晓得上面说的是啥意思,木关系,先笔记,待未来学习实践到这块再回过头来复习,自然就明白了。
b、Replace:
Replace - 用另一个路由替换指定的路由
- key - string - 被替换的路由的 key,如果未指定,最近的路由将会被替换
- newKey - string - 用于替换路线的 Key。 如果未提供,则自动生成。
- routeName - string - routeName用于替换路由。
- params - object - 要传入替换路由的参数。
- action - object - 可选的子动作。
- immediate* - boolean - 目前没有效果, 这是 stack navigator 支持动画替换(它目前不支持)的占位符。
c、Push:
Push - 在堆栈顶部添加一条路由,并导航至该路由. 与navigate的区别在于,如果有已经加载的页面,navigate方法将跳转到已经加载的页面,而不会重新创建一个新的页面。 push 总是会创建一个新的页面,所以一个页面可以被多次创建
- routeName - string - routeName用于替换路由。
- params - object - 将合并到目标路由的参数(通过this.props.navigation.state.params在目标路由获取)。
- action - Object - 可选 - (高级)如果页面是 navigator,则是在子路由器中运行的子操作。
比如:
import { StackActions } from 'react-navigation'; const pushAction = StackActions.push({ routeName: 'Profile', params: { myUserId: 9, }, }); this.props.navigation.dispatch(pushAction);
d、Pop:
The pop 一个可以返回到堆栈中上一个路由到方法,通过设置参数 n,可以指定返回的多少层。
- n - number - 返回的层数
import { StackActions } from 'react-navigation'; const popAction = StackActions.pop({ n: 1, }); this.props.navigation.dispatch(popAction);
e、PopToTop:
popToTop 一个可以直接跳转到堆栈最顶层,并销毁其它所有页面的方法,它在功能上与StackActions.pop({n:currentIndex})
相同。
import { StackActions } from 'react-navigation'; this.props.navigation.dispatch(StackActions.popToTop());
其实根据这些api的英文也大致知道是个啥意思,有点类似于Android Activity Stack。
安装使用指南:
上面理论完了之后,接下来则来使用一下它,先来上官网看一下:https://reactnavigation.org/
其中最新版已经到了6.x, 然而准备要演练的却是4.x的,好low呀,low就low吧,反正学习能力也有限,不管哪个技术都会有版本的问题,踏实先学好一个版本之后,未来对于新版的使用也比较简单,思想其实都是可以借鉴的,还是那句话,任何一个知识的学习都不会是孤立的,另外一个重要原因是为了跟所学习的教程保持一个较好的节奏。另外借鉴一下官网的两张图可以非常直观的了解React Navigation的用途:
相当形象。
4x版本的大特性:
navigator被拆分到不同的库中了:
所以,用到这些类型导航器的地方其引入方式也需要做相应的调整:
4x版本安装使用的正确方式:
4x版本对于的RN版本是0.6x,使用需要注意,目前我们使用的RN版本刚好就是它:
接下来则来使用吧。
第一步:新建一个RN DEMO工程
react-native init react_navigation_demo --version 0.62.2
然后为啥要指定0.62.2这个版本就不过多说明了,可以参考https://www.cnblogs.com/webor2006/p/14716461.html:
然后先运行一下,确保环境都ok,然后用webstorm打开工程:
第二步:安装主库
第三步:安装主库依赖的三方库
因为新版react-navigation依赖一些第三方库,所以安装时需要同时引入:
第四步:根据需要引入各导航组件的库
在上面不是说明了在4.x时navigator被拆分到不同的库中了么?
所以,需要都导入一下:
第四步:执行pob install
为了在ios上完成安装,还需要执行如下命令:
第五步:配置react-native-gesture-handler:
为了在Android上能够使react-native-gesture-handler有效,需要修改MainActivity.java,它主要是完成导航器手势滑动过程中手势的处理拦截之类的:
修改如下:
package com.react_navigation_demo; import com.facebook.react.ReactActivity; import com.facebook.react.ReactActivityDelegate; import com.facebook.react.ReactRootView; import com.swmansion.gesturehandler.react.RNGestureHandlerEnabledRootView; public class MainActivity extends ReactActivity { /** * Returns the name of the main component registered from JavaScript. This is used to schedule * rendering of the component. */ @Override protected String getMainComponentName() { return "react_navigation_demo"; } @Override protected ReactActivityDelegate createReactActivityDelegate() { return new ReactActivityDelegate(this, getMainComponentName()) { @Override protected ReactRootView createRootView() { return new RNGestureHandlerEnabledRootView(MainActivity.this); } }; } }
第六步:运行android和ios
此时为了确保react-navigation环境的安装,需要在android和ios都运行一下,如果没有报错正常运行那么恭喜,咱们的react-navigation环境就已经配置完成了,接下来就可以开启react-navigation学习之旅啦。
已知兼容问题:
当你在RN 0.61.0上使用react-navigation 4.0时你会发现,createMaterialTopTabNavigator在Android上左右滑动无效,这是一个已知的兼容问题。
该问题由“react-native”:“0.61.0-rc.0”的ReactActivityDelegate的改动引起,导致protected ReactRootView createRootView()不回调,所以react-navigation所使用的react-native-gesture-handler也就在android上无法监测到用户的手势,进而导致滑动切换tab失效。解决办法可以使用0.60.5版本的rn。
其它升级适配说明:
react-native中的AsyncStorage在未来的版本迭代中将会被从react-native中移除,官方推荐使用react-native-community/async-storage来代替:
安装方式 :
然后:
使用方式:
其他API不变。
FAQ:
1、Cannot get property 'supportLibVersion' on Extra properties extension as it does not exist.
问题描述:
升级到rn 0.61.0后报上述错误
解决方法:
在android/build.gradle中添加supportLibVersion:
2、Unsupported Modules Detected
问题描述:
解决办法:
删除Android下的./idea目录然后重新打开项目。
3、Android不显示矢量图标【关于矢量图标下面就会学到】
问题描述:
版本信息:
不报错但是不显示图标。
解决办法:
在android/app/build.gradle添加:
4、Update is invalid - A JS bundle file named "null"
问题描述:
Codepush jsbundle下载完成,更新时报错,如下:
解决办法:
在MainApplication.java中添加:CodePush.getJSBundleFile():
5、Error in getting binary resources modified time
问题描述:
Codepush检测更新,logcat上述错误
解决办法:
在android/app/build.gradle添加:
6、Unrecognized font family 'Ionicons' or 'Materiallcons'
问题描述:
启动IOS APP报错,无法加载字体文件:
版本信息:
无论是自动link还是手动link都会报这个错误。
解决办法:
第一步:切到ios目录执行install:
第二步:将下面配置粘贴到info.plist:
然后重新运行项目,如果问题依旧,用Xcode打开Github_RN.xcworkspace,然后改为用Xcode运行项目。
矢量图标:
在上面也提到了矢量图标,如今它在APP中的图标使用也越来越流行了,所以如何在RN中使用矢量图标也是一个刚需。
安装矢量图标:
它的github为:https://github.com/oblador/react-native-vector-icons
安装方式如下:
咱们是用的yarn,所以添加如下:
ios配置:
具体官网都有说明,这里直接来配置了:
1、Info.plist中增加如下配置:
<key>UIAppFonts</key> <array> <string>AntDesign.ttf</string> <string>Entypo.ttf</string> <string>EvilIcons.ttf</string> <string>Feather.ttf</string> <string>FontAwesome.ttf</string> <string>FontAwesome5_Brands.ttf</string> <string>FontAwesome5_Regular.ttf</string> <string>FontAwesome5_Solid.ttf</string> <string>Foundation.ttf</string> <string>Ionicons.ttf</string> <string>MaterialIcons.ttf</string> <string>MaterialCommunityIcons.ttf</string> <string>SimpleLineIcons.ttf</string> <string>Octicons.ttf</string> <string>Zocial.ttf</string> <string>Fontisto.ttf</string> </array>
2、切到ios目录执行install:
android配置:
1、android/app/build.gradle进行配置:
apply from: "../../node_modules/react-native-vector-icons/fonts.gradle"
项目中使用矢量图标:
对于支持的矢量图标,可以上这个官网去查找:https://oblador.github.io/react-native-vector-icons/
其中可以看到有很多分类:
比如我们要使用AntDesign这个类中的图标库,可以在项目中这样导入:
然后接下来就可以使用了,这里以两个图标为例:
运行:
先看一下android的效果:
再来看一下Ios上的效果,运行发现报错了。。
度娘上看到一篇文章:https://blog.csdn.net/ioth5/article/details/104253511,试试:
再次运行看一下:
嗯,跟android的效果一样。
总结:
关于导航器咱们这里只是搭建了一个基础环境,正式的使用待下次继续,另外由于每个人电脑的环境可能不一样,所以其运行出来可能不一定都一样,当然也有可能遇到不同样的问题,自行上网解决既可,学习本来就是模仿+超越的过程【对于我而言,当然对于纯大佬那直接超越就可以了~~】,模仿中遇到的各种问题正好是加深学习的一个很好的过程,篇幅有限,下次继续~~