React Native资料汇总React Native开发React-Native 开发阵营

ReactNative中SectionList实现条目GridV

2017-09-11  本文已影响640人  冯涛_简书

本文纯原创,纯手打,请大神多多指教。转载请注明出处!
react-native版本:0.48; 开发环境win10+VScode; 目标平台:安卓(暂时没有适配苹果); 最后更新时间:2017.09.11;

在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, ImageBackground, TouchableOpacity, ToastAndroid, SectionList, FlatList ,RefreshControl} 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: <Text style={{ alignSelf: 'center', fontSize: 16, color: 'black', }}>工作台</Text>,
         headerLeft: null,
         headerStyle: {
             height: 40,
         }
     }
    
     componentDidMount() {
         this._getModuleDefault()
     }
     _getModuleDefault() {
         console.log("令牌" + GV.ACCESS_TOKEN)
    
         if (GV.ACCESS_TOKEN !== '') {
             var url = 'http://api.test.zhu-ku.com/zhuku/ws/system/sysroleapp/selectUserRoleAll/' + GV.ACCESS_TOKEN;
             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 {
                         //alert(responseJson.statusDesc + 'response')
                         ToastAndroid.show('获取权限失败:' + responseJson.statusDesc, ToastAndroid.SHORT);
                     }
                     this.setState({
                         isLoading: false
                     })
    
                 })
                 .catch((error) => {
                     alert(error)
                     this.setState({
                         isLoading: false
                     })
                 })
             //ToastAndroid.show('132132', ToastAndroid.SHORT);
         }
     }
    
     _renderItem = ({ info }) => null
    
     _renderSectionHeader = ({ section }) =>
         <View>
             <Text style={styles.viewItemHeader}>{section.title}</Text>
             <FlatList
                 data={section.data}
                 style={styles.flastList}
                 numColumns={4}
                 renderItem={({ item }) =>
                     <TouchableOpacity onPress={item.onPress}>
                         <View style={styles.viewRow}>
                             <Image source={item.img} style={styles.imageItem} />
                             <Text style={styles.textItem}>{item.name}</Text>
                         </View>
                     </TouchableOpacity>
                 }
             />
         </View>
    
    
     render() {
         return (
             this.state.isLoading ?
                 <View style={styles.load}>
                     <Progress.CircleSnail style={{ margin: 10, alignSelf: 'center' }} color={['red', 'green', 'blue', 'black', 'yellow']} size={30} />
                     <Text>正在加载...</Text>
                 </View>
                 :
                 <SectionList
                     style={styles.background}
                     renderSectionHeader={this._renderSectionHeader}
                     renderItem={({ info }) => null}
                     sections={AllMenu}
                     //refreshing={this.state.isLoading}
                 />
    
         )
     }
    
     _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 (var index = 0; index < returnData.length; 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);//讲统计添加到模块集合
    
     }
    }
    
     
    
     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 default WorksView
    

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中返回图标

效果是这样的

上一篇 下一篇

猜你喜欢

热点阅读