apicloud中提供下拉刷新監聽事件api,也提供滾動到底部事件的監聽,可以實現下拉刷新和滾動到底部加載更多功能,可是咱們真的就知足實現功能了嗎?將兩個代碼拼湊起來運行看看發現了什麼?是的,在滾動到底部加載更多的時候底部會彈動,有人可能會說觸發加載更多的時候直接放一個遮罩view,也就是progress,用來禁止用戶繼續對當前view產生觸摸事件就行,可是若是你很快滑動到底部呢,彈動現象仍然不能禁止。我曾向技術屢次提過在下拉刷新api中提供一個參數用來控制是否禁用底部彈動的,可是前幾回技術都是不了了之,最近又問了一次,直接回應「目前市面上有APP是這種效果嗎?底部彈動,主要是擬物,跟手,你不喜歡這種效果,不表明每一個人都不喜歡。」,我只想說,我又沒叫你去掉彈動,只是加一個屬性控制是否彈動,這和別人是否喜歡有什麼關係,並且盡然還說如今市場的app有這種效果嗎?可能我已經脫離了市場軌道。好了,發發牢騷而已,這裏不談技術人員的態度問題,下面分享下我如何實現優雅控制的:javascript
對於這個問題我想過不少種辦法,本來想是否改寫官方底層來實現,可是嘗試了一下放棄了(好吧,我認可是我太水,沒改的了),由於就算我把Android改了,那IOS呢,apicloud引擎又沒有開源,IOS一樣沒法實現,那又有什麼意義,我想應該有不少人都糾結這個問題,那麼到底怎麼解決呢?css
首先apicloud提供了設置頁面bounces的方法,可否從這方面下手,動態改變其bounces狀態,在具備下拉意圖的時候開啓bounces,在具備上拉加載更多意圖的時候禁用bounces。可是如何判斷意圖呢,最初的設想是監聽scrolltobottom方法來控制,放滾動到距離底部還有50dp的時候來禁用bounces,在距離頂部50dp(經過計算成距離底部距離)的時候開啓bounces,可是發現scrolltobottom有些問題:一、只能監聽一個,不能任性的監聽,後面的會覆蓋前面的。二、滾動到距離底部50dp的時候觸發事件,可是滾動到距底部0dp的時候再向下滾任然會觸發該事件,這應該是一個bug。原生api使用不了,那js是否提供方法呢,都知道咱們的開始使用的是webview,雖然Java能夠直接調用webview的原生方法,可是js也能夠操做webkit的事件,其中就有onscroll事件,這個是網頁滾動的事件。可否經過這個方法來改變bounces呢,試驗了一下,還真能夠,整體方法就是在使用原生下拉刷新與scrolltobottom監聽滾動到底部的同時,使用js監聽頁面滾動事件,在滾動條距離頂部30像素位置上下分別改變bounces狀態。html
具體代碼:vue
<!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>