本文纯原创,纯手打,请大神多多指教。转载请注明出处!
react-native版本:0.48; 开发环境win10+VScode; 目标平台:安卓(暂时没有适配苹果); 最后更新时间:2017.09.11;
在ReactNative,想做个Android中分组GridView的效果,搜索了半天没找到解决办法,于是自己瞎摸索出来了一套效果,目前就是用SectionList嵌套FlatList,但是这肯定不是最优的方法,还请大神指点
先看下效果图
最终完成效果
-
数据格式
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.gitimport 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中返回图标
效果是这样的