apicloud中提供下拉刷新监听事件api,也提供滚动到底部事件的监听,能够实现下拉刷新和滚动到底部加载更多功能,但是我们真的就满足实现功能了吗?将两个代码拼凑起来运行看看发现了什么?是的,在滚动到底部加载更多的时候底部会弹动,有人可能会说触发加载更多的时候直接放一个遮罩view,也就是progress,用来禁止用户继续对当前view产生触摸事件就行,但是如果你很快滑动到底部呢,弹动现象仍然不能禁止。我曾向技术多次提过在下拉刷新api中提供一个参数用来控制是否禁用底部弹动的,但是前几次技术都是不了了之,最近又问了一次,直接回应“目前市面上有APP是这种效果吗?底部弹动,主要是拟物,跟手,你不喜欢这种效果,不代表每个人都不喜欢。”,我只想说,我又没叫你去掉弹动,只是加一个属性控制是否弹动,这和别人是否喜欢有什么关系,而且尽然还说现在市场的app有这种效果吗?可能我已经脱离了市场轨道。好了,发发牢骚而已,这里不谈技术人员的态度问题,下面分享下我如何实现优雅控制的:
对于这个问题我想过很多种办法,原本想是否改写官方底层来实现,但是尝试了一下放弃了(好吧,我承认是我太水,没改的了),因为就算我把Android改了,那IOS呢,apicloud引擎又没有开源,IOS同样无法实现,那又有什么意义,我想应该有很多人都纠结这个问题,那么到底怎么解决呢?
首先apicloud提供了设置页面bounces的方法,能否从这方面下手,动态改变其bounces状态,在具有下拉意图的时候开启bounces,在具有上拉加载更多意图的时候禁用bounces。但是如何判断意图呢,最初的设想是监听scrolltobottom方法来控制,放滚动到距离底部还有50dp的时候来禁用bounces,在距离顶部50dp(通过计算成距离底部距离)的时候开启bounces,但是发现scrolltobottom有些问题:1、只能监听一个,不能任性的监听,后面的会覆盖前面的。2、滚动到距离底部50dp的时候触发事件,但是滚动到距底部0dp的时候再向下滚任然会触发该事件,这应该是一个bug。原生api使用不了,那js是否提供方法呢,都知道我们的开始使用的是webview,虽然Java可以直接调用webview的原生方法,但是js也可以操作webkit的事件,其中就有onscroll事件,这个是网页滚动的事件。能否通过这个方法来改变bounces呢,试验了一下,还真可以,总体方法就是在使用原生下拉刷新与scrolltobottom监听滚动到底部的同时,使用js监听页面滚动事件,在滚动条距离顶部30像素位置上下分别改变bounces状态。
具体代码:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta name="viewport" content="maximum-scale=1.0,minimum-scale=1.0,user-scalable=0,width=device-width,initial-scale=1.0"/> <meta name="format-detection" content="telephone=no,email=no,date=no,address=no"> <title>邂逅</title> <link rel="stylesheet" type="text/css" href="../css/aui.css"/> <style type="text/css"> .aui-list-item.wechat-top { background-color: #f3f3f7; } .aui-list .wechat-avatar { width: 3rem; } .wechat-avatar .aui-row-padded { background-color: #dddee0; padding: 0.1 rem; border-radius: 0.2 rem; margin-left: -0.05 rem; margin-right: -0.05 rem; } .wechat-avatar .aui-row-padded { padding: 0.05 rem; } .wechat-avatar, .wechat-avatar > img { border-radius: 0.2 rem; } </style> </head> <body> <div class="aui-content aui-margin-b-15" id="aui-content"> <ul class="aui-list aui-media-list"> <li class="aui-list-item aui-list-item-middle" v-for="item in itemList"> <div class="aui-media-list-item-inner"> <div class="aui-list-item-media wechat-avatar"> <img :src="[item.HeadIcon]" /> </div> <div class="aui-list-item-inner"> <div class="aui-list-item-text"> <div class="aui-list-item-title"> {{item.NickName}} </div> <div class="aui-list-item-right"> {{item.ResidenceCity}} </div> </div> <div class="aui-list-item-text aui-font-size-12"> 愿得一人心,白首不分离 </div> </div> </div> </li> </ul> </div> </body> <script type="text/javascript" src="../script/api.js"></script> <script type="text/javascript" src="../script/common.js"></script> <script type="text/javascript" src="../script/vue.min.js"></script> <script type="text/javascript"> var bounce = true, self = this; var pageNum = 1, pageSize = 10; var vm = new Vue({ el : ".aui-content", data : { itemList : [], count : 0, pageEnd : false } }); apiready = function() { var minHeight = api.frameHeight + 30; var div = $api.byId('aui-content'); div.style.cssText="min-height:"+minHeight+"px"; api.setRefreshHeaderInfo({ loadingImg : 'widget://image/refresh.png', bgColor : '#ccc', textColor : '#fff', textDown : '下拉刷新...', textUp : '松开刷新...' }, function(ret, err) { //在这里从服务器加载数据,加载完成后调用api.refreshHeaderLoadDone()方法恢复组件到默认状态 reloadList(); setTimeout('api.refreshHeaderLoadDone()', '500'); }); api.addEventListener({ name : 'scrolltobottom', extra : { threshold : 0 //设置距离底部多少距离时触发,默认值为0,数字类型 } }, function(ret, err) { if (vm.pageEnd) { api.toast({ msg : '没有更多数据了' }) } else { getList(); } }); reloadList(); window.addEventListener("scroll", function() { var t = document.documentElement.scrollTop || document.body.scrollTop; if (t <= 30) { if (!bounce) { api.setFrameAttr({ name : 'search_frm', bounces : true, }); bounce = true; } } else { if (bounce) { api.setFrameAttr({ name : 'search_frm', bounces : false, }); bounce = false; } } }); }; function getList() { api.showProgress({ title : '努力加载中...', text : '请稍后...', modal : false }); api.ajax({ url : host + "/api/User/AllUserList?pageNum=" + pageNum + "&pageSize=" + pageSize, method : "get" }, function(ret, err) { if (ret) { if (ret.code == 200) { if (!ret.res.data.list) { api.toast({ msg : '没有更多数据了' }) } else { if (ret.res.data.count < pageSize) { vm.itemList = vm.itemList.concat(ret.res.data.list); vm.count = ret.res.data.count; api.toast({ msg : '没有更多数据了' }); vm.pageEnd = true; } else { vm.itemList = vm.itemList.concat(ret.res.data.list); vm.count = ret.res.data.count; pageNum++; } } } } else { alert("网络异常,请稍后再试吧") } setTimeout('api.hideProgress()', '500'); }) } function reloadList() { pageNum = 1; api.showProgress({ title : '努力加载中...', text : '请稍后...', modal : false }); api.ajax({ url : host + "/api/User/AllUserList?pageNum=" + pageNum + "&pageSize=" + pageSize, method : "get" }, function(ret, err) { if (ret) { if (ret.code == 200) { if (!ret.res.data.list) { api.toast({ msg : '没有更多数据了' }) } else { vm.itemList = ret.res.data.list; vm.count = ret.res.data.count; vm.pageEnd = false; pageNum++; } } } else { alert("网络异常,请稍后再试吧") } setTimeout('api.hideProgress()', '500'); }); } </script> </html>