ReactNative中SectionList实现条目GridV

作者: 冯涛_简书 | 来源:发表于2017-09-09 18:10 被阅读1478次

    本文纯原创,纯手打,请大神多多指教。转载请注明出处!

    react-native版本:0.48;  开发环境win10+VScode;  目标平台:安卓(暂时没有适配苹果);  最后更新时间:2017.09.11;


    本文我又把编辑器改成MD重新发布了,建议浏览新地址 http://www.jianshu.com/p/a787d9af2401 

    在ReactNative,想做个Android中分组GridView的效果,搜索了半天没找到解决办法,于是自己瞎摸索出来了一套效果,目前就是用SectionList嵌套FlatList,但是这肯定不是最优的方法,还请大神指点

    先看下效果图

    最终完成效果

    1. 数据格式

    var data0={name:'外勤签到',img:Images.oaWQQD,onPress:()=>alert('跳转页面----外勤签到') }

    var data1={name:'考勤打卡',img:Images.oaKQDK}

    var data2={name:'审批',img:Images.oaSP}

    var data3={name:'日志',img:Images.oaRZ}

    OAData.push(data0)

    OAData.push(data1)

    OAData.push(data2)

    var AllMenu2=[

    {key:0,title:'办公',data:OAData},

    {key:1,title:'营销',data:YXData},

    ]

    2.代码

    源代码地址:https://github.com/MyPublicGitHub/Test.git

    import React from'react'

    import{

        StyleSheet,View,Image,Text,TouchableOpacity,ToastAndroid,

        SectionList,FlatList

    }from'react-native'

    import Images from'../images/ImageList'

    import Api from'../api/Api'

    import GV from'../utils/GlobalVariable'

    import * as Progress from'react-native-progress';

    var AllMenu=[];

    var Dimensions=require('Dimensions');//获取屏幕的宽高

    var ScreenWidth=Dimensions.get('window').width;

    var ScreenHeight=Dimensions.get('window').height;

    class WorksView extends React.Component{

        constructor(props) {

            super(props);

            this.state={

                isLoading:false,

            };

          }

          static navigationOptions={

                headerTitle:工作台,

               headerLeft:null,

               headerStyle:{

                      height:40,

                } 

          }

    componentDidMount() {

             this._getModuleDefault()

    }

    _getModuleDefault() {

              if(GV.ACCESS_TOKEN!=='') {

                     var url='网络地址';

                      var header={

                      method:'get',

              }

               this.setState({

                     isLoading:true

               })

               fetch(url,header)

                .then((response)=>{

                       return response.json()

                 })

                .then((responseJson)=>{

                        if(responseJson.statusCode=='0000') {

                               ToastAndroid.show('成功',ToastAndroid.SHORT);

                              this._initItem(responseJson.returnData);

                         }else{

                                ToastAndroid.show('失败:'+responseJson.statusDesc,ToastAndroid.SHORT);

                         }

                          this.setState({

                                 isLoading:false

                         })

                    })

                  .catch((error)=>{

                           alert(error)

                          this.setState({

                                 isLoading:false

                          })

                   })

         }

    }

    _renderItem=({info})=>null

    _renderSectionHeader=({section})=>

          <View>

               

    render() {

    return(

    this.state.isLoading?

    正在加载...

    :

    style={styles.background}

    renderSectionHeader={this._renderSectionHeader}

    renderItem={this._renderItem}

    sections={AllMenu}

    />

    )

    }

    _initItem(returnData) {

    var OAData=[]

    var YXData=[]

    var CGData=[]

    var TJData=[]

    //OA模块数据是固定的

    var data0={name:'外勤签到',img:Images.oaWQQD,onPress:()=>alert('外勤签到') }

    var data1={name:'考勤打卡',img:Images.oaKQDK}

    var data2={name:'审批',img:Images.oaSP}

    var data3={name:'日志',img:Images.oaRZ}

    var data4={name:'任务',img:Images.oaRW}

    var data5={name:'公告',img:Images.oaGG}

    var data6 ={name:'证书',img:Images.oaZS}

    var data7={name:'印章',img:Images.oaYZ}

    var data8={name:'资产',img:Images.oaZC}

    var data9={name:'车辆',img:Images.oaCL}

    //把数据添加到办公子模块

    OAData.push(data0)

    OAData.push(data1)

    OAData.push(data2)

    OAData.push(data3)

    OAData.push(data4)

    OAData.push(data5)

    OAData.push(data6)

    OAData.push(data7)

    OAData.push(data8)

    OAData.push(data9)

    //循环找出拥有权限的模块

    for(varindex=0;index

    var element=returnData[index];

    var menuId=element.menuId;

    if(menuId==16) {

    YXData.push({name:'项目信息',img:Images.yxXMXY})

    }

    if(menuId==17) {

    YXData.push({name:'营销任务',img:Images.yxYXRW})

    }

    if(menuId==18) {

    YXData.push({name:'同行分析',img:Images.yxTHFX})

    }

    if(menuId==19) {

    YXData.push({name:'投标管理',img:Images.yxTBGL})

    }

    if(menuId==20) {

    YXData.push({name:'业绩PK',img:Images.yxYJPK})

    }

    if(menuId==21) {

    YXData.push({name:'客户看板',img:Images.yxKHKB})

    }

    //采购

    if(menuId==29) {

    CGData.push({name:'供应商',img:Images.cgGYS})

    }

    if(menuId==30) {

    CGData.push({name:'物资采购',img:Images.cgWZCG})

    }

    if(menuId==31) {

    CGData.push({name:'供应商评价',img:Images.cgGYSPJ})

    }

    if(menuId==32) {

    CGData.push({

    name:'供应商往来',img:Images.cgGYSWL,onPress:()=>alert('供应商往来')

    })

    }

    //统计

    if(menuId==8) {

    TJData.push({name:'管理统计',img:Images.tjGLTJ})

    TJData.push({name:'项目统计',img:Images.tjXMTJ})

    }

    }

    var OAMenu={key:0,title:'办公',data:OAData}//把办公子模块添加到办公模块

    var YXMenu={key:1,title:'营销',data:YXData}//把营销子模块添加到营销模块

    var CGMenu={key:2,title:'采购',data:CGData}//把采购子模块添加到采购模块

    var TJMenu={key:3,title:'统计',data:TJData}//把统计子模块添加到统计模块

    AllMenu.push(OAMenu);//讲办公添加到模块集合

    AllMenu.push(YXMenu);//讲营销添加到模块集合

    AllMenu.push(CGMenu);//讲采购添加到模块集合

    AllMenu.push(TJMenu);//讲统计添加到模块集合

    }

    }

    conststyles=StyleSheet.create({

    load:{

    flex:1,

    justifyContent:'center',

    alignItems:'center',

    },

    background:{

    flex:1,

    backgroundColor:'white'

    },

    viewItemHeader:{

    flex:1,

    backgroundColor:'#eeeeee',

    alignItems:'center',

    paddingLeft:20,

    paddingTop:5,

    paddingBottom:5,

    },

    viewRow:{

    // flexDirection: 'row',//设置横向布局

    justifyContent:'center',

    alignItems:'center',

    width:ScreenWidth/4,

    padding:10,

    },

    imageItem:{

    height:40,

    width:40,

    },

    textItem:{

    textAlignVertical:'center',

    color:'#5C5C5C',

    fontSize:12,

    },

    flastList:{

    },

    })

    export defaultWorksView

    3.总结

    简书还是不智能,复制的代码 全部去掉看空格,我已经优化了一下,可能有的地方报错,需要补空格。

    我在代码中没有用到SectionList中的keyExtractor属性,可能有些地方会报黄色警告,建议大家把文中的title字段作为key。

    关于SectionList的属性请到ReactNative中文网 了解

    条目层级

    4.遇到的坑

    4.1 如果把FlatList写到renderIten方法中会出现这样的情况

    把标题写到renderSectionHeader中把FlatList写到renderItem中 会发现sectinItem不显示了

    我猜测,这种情况是因为数据格式不对导致的,renderItem方法的参数是(info: {item: Item, index: number}) => ?所以参数全部都是数组中的对象信息(本文中是:{name:'营销任务',img:Images.yxYXRW})但是,FlatList需要的数据格式是整个条目的数组

    4.2 如果直接在renderItem中返回子条目

    如果按照常规的逻辑,我们大概会这样写,写出来的效果比较适合做通讯录等,每个item占用一行。而不能把item 进行Z型排列;这是系统默认的效果,我在这个基础上摸索了半天 没处理好,还请大神指点


    header返回text,item中返回图标

    效果是这样的





    相关文章

      网友评论

      • 702d697f68c3:你这有些画蛇添足啊,SectionList 本身就能实现这个效果。。。为什么还要在里面镶嵌FlatList,,
        不要看中文api,看他英文的那个,再看他底层 继承的谁,再看他继承的那个里面的方法
      • 5997854c43de:实现效果不是横向显示的呀
      • f3511ac6291e:小伙子。写的太过牛逼了 其实我用最简单的list view 就实现了,核心是设置flexdirection:row flexwrap:flexwrap 就实现了 哪有这么复杂:joy:
        冯涛_简书:@猪猪侠9527 listView已经有点老了,太消耗资源。不过我这个确实也只是粗糙的解决
      • 抱歉我孤独成性视你如命i:创新思路很厉害,给你1024个赞
      • f40dade33aa1:讲道理,写的是不错。但是中间bug问题还是没有解决
      • 深港澳第一程序员:我做安卓90年,被誉为深港澳第一程序员。一直不明白的react native竟然在你的博文中看到了思路。
      • 3aac372d3350:哇,这篇文章真的良心,我刚好也一直被这个问题难住,每次都感觉自己想来想去想不通,我做安卓60年了,从来没遇到这样的难题,但是今天,在这里,这篇文章让我恍然大悟,兄弟你真的可以,我认你为就是年来我遇到的最强的一个!
      • 7b6b3d1bbebd:写得很好啊,这个问题一直找不到解决办法,在你这找到了🤗感谢!已经解决了!
      • 3aac372d3350:看到这个界面完全就断了我接着看下去的念头,小伙子,你的审美还是不行,虽然我没看代码,但是我知道你写的东西。。。。有bug
        狂野的骚猪:@冯涛_简书 UI没错,只是你的逻辑有点多余了
        冯涛_简书:哈哈哈,这是我公司出的UI

      本文标题:ReactNative中SectionList实现条目GridV

      本文链接:https://www.haomeiwen.com/subject/gnyrsttx.html