React Native 支付宝更多页面的实现
2018-07-24 本文已影响560人
IT界的段子手
效果图
- 实现的效果:
- 页面向上滑动有吸顶的效果。
-
便民服务,查询服务 ...所在的tabBar与页面下方对应的模块内容一一对应。 - 页面滑动对应的
tabBar的title居中偏移。 - 编辑模式下:数据的
新增与删除。
-
效果展示:
实现效果图.gif
-
实现吸顶的代码(噗~感觉这个没啥好写 ...... 很尴尬):
—— 段子手是运用ScrollView==>onScroll==>e.nativeEvent.contentOffset.y获取页面滑动的当前坐标;
然后和页面初次加载时tabBar==>onLayout==>e.nativeEvent.layout.y的值做比较获取状态。this.moveHeight = e.nativeEvent.contentOffset.y; if (this.moveHeight >= typeY) { this.setState({ positionType: true, }) } else { this.setState({ positionType: false }) } -
实现滑动模块和标题一一对应代码(这个有点篇幅):
-
先说:点击标题,对应的模块自动置顶
- 首先初次加载时,我把
tabBar下的各个模块的y坐标都存下来,push到数组中,并且对应的模块下标i也存起来。
//保存 模块的下标和 y 轴 let params = { key: i, tmpY: e.nativeEvent.layout.y }; //数组去重(判断命名的变量不建议用 type) let typePis = tmpArr.some(v => v.key == params.key); if (typePis) { tmpArr.filter((v) => { return v.key != params.key }) } else { tmpArr.push(params); } break;- 去重是因为吸顶的原因,会导致页面的
onLayout重新加载。 - 这里还有一个小坑:模块返回的坐标顺序并不是按页面展示顺序来的。
- 拿到模块的坐标数组
tmpArr后,根据点击tabBar的下标index和tmpArr的key去匹配,一致时取出tmpArr对应的tmpY值,根据该值去计算页面的偏移量。
let y; tmpArr.map((v, i) => { if (v.key == index) { y = v.tmpY; } }); // 页面中模块的 y 轴移动 (typeY: tabBar 的坐标, // y:模块的坐标,头部 固定位置的搜索: autoHeight(45)) this.refs.refMoveHeight.scrollTo({y: typeY + y - autoHeight(45)});- 在点击
tabBar最后的标题,模块的内容的高度不够去偏移到置顶的位置的处理(根据已有的内容高度,去自适应填充空白区域)。- 保存最后一个模块的
y轴
// i:就是点击标题的下标;typeList:是标题数组。 if (i == typeList.length - 1) { this.setState({ listCellHeight: e.nativeEvent.layout.y }) }- 在最后的一个模块后面添加一个高度为
1的View,然后保存它的坐标footHeight = e.nativeEvent.layout.y,接着再设置一个填充空白页面View,高度为屏幕全高 - (footHeight - listCellHeight - typeY + autoHeight(45))。
- 保存最后一个模块的
- 首先初次加载时,我把
-
再说下滑动模块和
tabBar的标题对应- 获取手势在屏幕上的滑动方向,把
<=当前页面滑动高度的模块都塞选出来,然后取出最大的下标,然后和tabBar中的标题下标去匹配,一致则标题显示高亮。let maxValue = 0; if (this.moveHeight > e.nativeEvent.contentOffset.y) { tmpArr.map((v, i) => { if (e.nativeEvent.contentOffset.y >= (typeY + v.tmpY - autoHeight(45))) { // console.log(i + '下下下'); //因为模块高度的下标不是按在页面中的位置返回的,所以和 tabBar 的下标并不能一一对应,所以要塞选出下标的最大值 if (tmpArr[i].key >= maxValue) { maxValue = tmpArr[i].key } // console.log(maxValue + 'maxValue下========='); } } ) } else { tmpArr.map((v, i) => { if (e.nativeEvent.contentOffset.y >= (typeY + v.tmpY - autoHeight(45))) { // console.log(i + '下下下'); //因为模块高度的下标不是按在页面中的位置返回的,所以和 tabBar 的下标并不能一一对应,所以要塞选出下标的最大值 if (tmpArr[i].key >= maxValue) { maxValue = tmpArr[i].key } // console.log(maxValue + 'maxValue上======'); } } ) } this.state.currentIndex = maxValue;
- 获取手势在屏幕上的滑动方向,把
-
-
实现页面滑动对应的
tabBar的title居中偏移代码-
获取屏幕
width的宽度的一半。let widthHalf = 屏幕宽度 / 2; -
获取到
tabBar中各个标题位置的width,同时保存对应的挑剔位置的下标,数组为tmpArrX。//保存 tabBar 的下标和 width let param = { index: i, tmpX: e.nativeEvent.layout.width }; //数组去重 let tmpType = tmpArrX.some(v => v.index == param.index); if (tmpType) { tmpArrX.filter((v) => { return v.index != param.index }) } else { tmpArrX.push(param); } -
拿到点击
tabBar的下标,获取到这个下标之前的模块width。//获取 index 之前模块 width let widthX = 0; //获取选中的 width let indexWidth; for (let i = 0; i <= index; i++) { // console.log('i===' + i); tmpArrX.map((item, key) => { if (item.index == i) { widthX += item.tmpX } if (index == item.index) { indexWidth = item.tmpX } }) } -
根据判断出来是不是
tabBar中最后一个标题,然后拿widthX和indexWidth然后去判断编写逻辑。let moveX; // index*20 是每个模块的空隙 20 if (widthX + index * 20 > widthHalf && index != tmpArrX.length - 1) { moveX = (widthX - widthHalf + indexWidth) / 2 } else if (index == tmpArrX.length - 1) { //index + 1 :间距比个数多一个; 10 :marGinLeft = 10 moveX = (index + 1) * 20 + widthX - SCREEN_WIDTH + 10 } // 页面中 tabBar 的 x 轴移动 this.refs.moveX.scrollTo({x: autoWidth(moveX)})
-
-
实现编辑模式下:数据的
新增与删除的代码(段子手快饿死了,写不动注释了 ......)//数组的加减 _addOrDelete(keyType, data, i) { console.log('data===' + JSON.stringify(data) + '===' + i); //更改 severListType 的数据 const {severListType, headList}=this.state; let tmpType = severListType.some(item => item.id === data.id); switch (keyType) { case 1: // severListType.splice(i, 1); if (tmpType) { // tmpSeverId :用来存储选中的截取的 id this.state.severListType = severListType.filter((item) => { return item.id != data.id }); //编辑模式下,是否为已有模块, true:加号,false:减号 data.select = !tmpType; } break; case 2: case 3: if (!tmpType) { if (severListType.length > 10) { RootToast.show('首页最多添加 11 个应用') } else { severListType.push(data) } } else { //获取输入的值和在另一个模块数组中的下标,然后删除 console.log('data1===' + JSON.stringify(data) + '===ss' + i); console.log('severListType===' + JSON.stringify(severListType)); this.state.severListType = severListType.filter((item) => { return item.id != data.id }); data.select = !tmpType; } break; } //刷新数据 this.setState({ severListType: this.state.severListType }, () => { // console.log('severListType===' + JSON.stringify(this.state.severListType)); }); }
TIP:
- 吸顶效果在
android低配中会出现卡顿现象。 - 页面滑动对应的
tabBar的title居中偏移(我的写法还是有问题的,还有就是模块滑动时tabBar对应居中也会有卡顿)。
段子手不才,欢迎来补充
- 由于篇幅原因,具体想要知道整个效果图的代码或者有补充地方的可以加技术群:631730313