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的作用。

  • 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的效果一样。

总结:

关于导航器咱们这里只是搭建了一个基础环境,正式的使用待下次继续,另外由于每个人电脑的环境可能不一样,所以其运行出来可能不一定都一样,当然也有可能遇到不同样的问题,自行上网解决既可,学习本来就是模仿+超越的过程【对于我而言,当然对于纯大佬那直接超越就可以了~~】,模仿中遇到的各种问题正好是加深学习的一个很好的过程,篇幅有限,下次继续~~

原文地址:https://www.cnblogs.com/webor2006/p/14733646.html