zoukankan      html  css  js  c++  java
  • 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的效果一样。

    总结:

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

  • 相关阅读:
    Elementary Methods in Number Theory Exercise 1.2.25
    Elementary Methods in Number Theory Exercise 1.2.14
    图解欧几里德算法
    图解欧几里德算法
    Elementary Methods in Number Theory Exercise 1.2.14
    Android中的长度单位详解(dp、sp、px、in、pt、mm)
    分享下多年积累的对JAVA程序员成长之路的总结
    android异常之都是deamon惹的祸The connection to adb is down, and a severe error has occured.
    TomatoCartv1.1.8.2部署时报错
    JavaScript浏览器对象之二Document对象
  • 原文地址:https://www.cnblogs.com/webor2006/p/14733646.html
Copyright © 2011-2022 走看看