apicloud如何实现优雅的下拉刷新与加载更多(Appcan也可类似实现)

  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 lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport"
          content="target-densitydpi=device-dpi,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/ui-base.css" />
    <link rel="stylesheet" type="text/css" href="css/ui-box.css" />
    <link rel="stylesheet" type="text/css" href="css/ui-color.css" />
    <link rel="stylesheet" type="text/css" href="css/ui.control.css" />
    <link rel="stylesheet" type="text/css" href="css/load_more.css" />
    <style>
        html,body{
            width:100%;
            height:100%;
        }
    </style>
</head>
<body class="um-vp">
    <div id="page_0" class="up ub ub-ver">
        <div id="content" class="ub ub-ver" style="min-height: 300px;">

        </div>
        <div id="loading" class="ub ub-ver" style="background:rgba(0,0,0,0.2);margin-top:5px"></div>
    </div>
</body>
<script type="text/javascript" src="./script/zepto.min.js"></script>
<script src="script/api.control.js"></script>
<script src="script/templete/template.js"></script>
<script src="script/ui.widget/ui.listview.js"></script>
<script src="script/zepto.widget/zepto.nodata.js"></script>
<script>
    ;(function($){
        $(function () {
            var con={
                listview: $.listview({
                    selector: "#content",
                    type: "thickLine",
                    hasAngle: false,
                    hasIcon: false,
                    hasSmallIcon:false,
                    multiLine: 1,
                }),
                pageindex:0,
                items:20,
                hasmore:false,
                times:0,
                isloading:false,
                getData:function(){
                    var self=this;
                    $("#content").empty();
                    $("#loading").empty();
                    var data=[];
                    switch (self.times){
                        case 0://无数据
                            break;
                        case 1://5条数据,不足一个屏幕
                            for(var i=0;i<5;i++){
                                data.push({
                                    title:"测试数据1"
                                });
                            }
                            break;
                        case 2://15条数据,超过一个屏幕,但是不足20条,没有加载更多
                            for(var i=0;i<15;i++){
                                data.push({
                                    title:"测试数据2"
                                });
                            }
                            break;
                        case 3://20条,表示可能有更多数据
                            for(var i=0;i<20;i++){
                                data.push({
                                    title:"测试数据3"
                                });
                            }
                            break;
                    }
                    if(data.length>0){
                        self.listview.add(data,1);
                    }
                    self.logic(data);
                    if(self.times>=3){
                        self.times=0;
                    }else{
                        self.times++;
                    }
                },
                logic: function(data) {
                    var self = this;
                    var boxdom=$("#content");
                    if (boxdom.children().length == 0&&data.length==0) { //从无数据开始
                        boxdom.nodata();
                    }else{
                        if (data.length == 0) {
                            self["hasmore"]= false;
                            if($("#content").find(".ui-nodata")){
                                //如果已经显示无数据则不进行append操作
                            }else{
                                $("#loading").empty().append(‘<div class="loading_more pause"><div id="loadingglobe" class="sk-spinner sk-spinner-wordpress uhide"><span class="sk-inner-circle"></span></div></div>‘);
                            }
                            return;
                        } else {
                            if (boxdom.offset().height > document.body.clientHeight) {
                                if(data.length<self.items){
                                    self["hasmore"]= false;
                                    $("#loading").empty().append(‘<div class="loading_more pause"><div id="loadingglobe" class="sk-spinner sk-spinner-wordpress uhide"><span class="sk-inner-circle"></span></div></div>‘);
                                }else{
                                    self["hasmore"]= true;
                                    $("#loading").empty().append(‘<div class="loading_more"><div id="loadingglobe" class="sk-spinner sk-spinner-wordpress uhide"><span class="sk-inner-circle"></span></div></div>‘);
                                }
                            }
                        }
                    }
                },
                loadData: function () {
                    var self=this;
                    var data=[{
                        title:"测试数据4",
                    },{
                        title:"测试数据4",
                    }];
                    self.listview.add(data,1);
                    self.logic(data);
                    self.isloading=false;
                },
                init: function () {
                    var bounce=true,self=this;
                    $.apiready(function () {
                        api.setRefreshHeaderInfo({
                            visible: true,
                            bgColor: ‘#ccc‘,
                            textColor: ‘#fff‘,
                            textDown: ‘下拉刷新...‘,
                            textUp: ‘松开刷新...‘,
                            showTime: true
                        }, function(ret, err){
                            setTimeout(function () {
                                self.getData();
                                api.refreshHeaderLoadDone();
                            },2000)
                        });
                        api.addEventListener({
                            name:‘scrolltobottom‘,
                            extra:{
                                threshold:0
                            }
                        },function(ret,err){
                            if(self.hasmore&&!self.isloading){
                                $("#loadingglobe").removeClass("uhide");
                                $("#loading .loading_more").addClass("active");
                                self.isloading=true;
                                setTimeout(function () {
                                    self.loadData();
                                },3000)
                            }
                        });
                        $.showProgress();
                        setTimeout(function () {
                            self.getData();
                            $.closeProgress();
                        },3000)
                    });
                    window.addEventListener("scroll",function(){
                        var t = document.documentElement.scrollTop || document.body.scrollTop;
                        if(t<=30){
                            if(!bounce){
                                api.setFrameAttr({
                                    name: ‘con‘,
                                    bounces: true,
                                });
                                bounce=true;
                            }
                        }else{
                            if(bounce){
                                api.setFrameAttr({
                                    name: ‘con‘,
                                    bounces: false,
                                });
                                bounce=false;
                            }
                        }
                    });
                }
            };
            con.init();
        })
    })(Zepto)
</script>
</html>

  具体体验效果可以下载使用:

    

  在Appcan论坛中也有人曾经问过如何实现的,希望能够参考一下实现,或许有人说使用js监听滚动事件是不是会影响webiew效率,此处不做研究,以后会做优化调整

时间: 2024-10-09 21:12:28

apicloud如何实现优雅的下拉刷新与加载更多(Appcan也可类似实现)的相关文章

10.下拉刷新、加载更多、标记已读、轮播条、缓存

下拉刷新.加载更多.标记已读.轮播条.缓存 下拉刷新------- 1.addHeaderView必须在setAdapter之前调用 2.将paddingTop设置一个headerView高度的负值去隐藏它 getHeight()和getMeasuredHeight()的区别: getMeasuredHeight():获取测量完的高度,只要在onMeasure方法执行完,就可以用 它获取到宽高,在自定义控件内部多使用这个 使用view.measure(0,0)方法可以主动通知系统去测量,然后就

retrofit+rxjava+recyclerview+下拉刷新+自动加载更多

安卓开发过程中,网络请求与下拉刷新分页列表的控件几乎可以说是必不可少的,但是每次开发一款产品都要重新开发,肯定是不可取的,那么最好是可以自己整理一个开发框架,那么以后开发,直接引入项目即可 网络框架的封装,从httpclient,到xutils,再到volley,再到okhttp,每次整合都发现多多少少的不足,目前自己觉得最成熟的一个也就是retrofit+okhttp3+rxjava的组合,rxjava不懂的推荐看大神的深入浅出rxjava,retrofit的使用自己网上搜咯 下拉刷新列表的实

自定义RecyclerView实现下拉刷新,加载更多

RecyclerView出来的时间已经不短了,现在估计大部分的列表类的需求实现首选肯定是RecyclerView,基本上可以跟ListView说再见了.那么问题来了,一般情况下一个列表页面都会有下拉刷新和加载更多功能,RecyclerView本身并没有下拉刷新和加载更多功能,当然现在已经有很多优秀的开源的支持下拉刷新,加载更多功能的三方RecyclerView,可以直接拿过来用.但是...有时候光会用是不够的,还需要知道它们是这么实现的,实现的原理是什么.下面就来介绍一下RecyclerView

自己定制ListView,上拉刷新和下拉刷新,加载网络图片,并且添加缓存机制。

1 package com.lixu.listviewrefresh; 2 3 import java.util.ArrayList; 4 import java.util.HashMap; 5 import java.util.Random; 6 7 import com.lixu.listviewrefresh.Loadnetimage.OnLoadnetimageListener; 8 import com.lixu.listviewrefresh.MyRefreshListview.On

IOS控件 Tableview 下拉刷新,加载数据

一. 点击此连链接下载资源文件,将EGORefreshTableHeaderView.h.EGORefreshTableHeaderView.m两个文件,以及Enormego提供的那一套图片包拖进你的工程里. 二.找到你的  UITableViewController 的 .h 文件,添加相应的代码: #import "EGORefreshTableHeaderView.h" @interface RootViewController : UITableViewController {

vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件

vue10行代码实现上拉翻页加载更多数据,纯手写js实现下拉刷新上拉翻页不引用任何第三方插件/库 一提到移动端的下拉刷新上拉翻页,你可能就会想到iScroll插件,没错iScroll是一个高性能,资源占用少,无依赖,多平台的javascript滚动插件.iScroll不仅仅是 滚动.它可以处理任何需要与用户进行移动交互的元素.在你的项目中包含仅仅4kb大小的iScroll,你的项目便拥有了滚动,缩放,平移,无限滚动,视差滚动,旋转功能.iScroll的强大毋庸置疑,本人也非常欢迎大家使用iScr

python selenuim如何判断下拉框是否加载出来,超过时间不再等待

s_flag = True time_start = time.time() while s_flag: doc = etree.HTML(unicode.encode(driver.page_source, encoding='utf-8')) from_list = doc.xpath("""//*[@id="ext-gen267"]/div""") if len(from_list) == 0: time_end = t

整合了刷新、加载更多、滑动删除功能的XListview

转载请说明出处:http://blog.csdn.net/bz419927089 如果想做带有刷新.加载更多功能的listview,我们可以使用XListview.(已经停止维护,github地址:https://github.com/Maxwin-z/XListView-Android) 如果想做带有滑动删除功能的listview,我们可以使用SwipeListview.(github地址:https://github.com/47deg/android-swipelistview) 如果想做

JQ-滚动条下拉无限的加载数据

一.原理 利用滚动的高度,如果滚动的高度到达一定范围,就加载数据 二.实现 利用$(document.body).outerWidth()获取的是屏幕的高度,这个是固定的,不变的 利用$(window).scrollTop()获取您滚动的高度 利用$(document).height()获取总的高度 注:$(widnow).height()这个是可视区的高度,这个跟$(document).height()很容易混淆 三.上代码 <section> <div id="tishi&