hml5 自定义滑动控件

ys_scroll.css

.ys-scroll-wrapper{
    position:relative;
    overflow: auto;
    -webkit-overflow-scrolling: touch;
}

.ys-scroll-wrapper .ys-scroll-content{
    min-height:100%;
}

/* loading-top */
.ys-scroll-wrapper .loading-top {
    display:block;
    width:100%;
    height:40px;
    line-height: 40px;
    text-align: center;
}
/* loading-bottom */
.ys-scroll-wrapper .loading-bottom {
    display:block;
    width:100%;
    height:40px;
    line-height: 40px;
    text-align: center;
}

/* loading-bottom */
.ys-scroll-wrapper .loading-end {
    display:none;
    width:100%;
    height:40px;
    line-height: 40px;
    text-align: center;
}

ys_scroll.js

(function($){

    var defaultSettings = {
        hasArrivedEnd:false,// 是否已经到底部
        pulldownCallback:function(){ // 下拉回调
            console.log("pull down ... ");

        },
        pullupCallback:function(){ // 上拉回调
            console.log("pull up ... ");
        }
    };

    function render(target,settings){

        var container = target;
        var childrenNode = $(container).children().remove();
        $(container).addClass("ys-scroll-wrapper");

        $(container).append("<div class=‘loading-top‘>加载中...</div>");
        $(container).append("<div class=‘ys-scroll-content‘></div>");
        $(container).append("<div class=‘loading-bottom‘>加载更多...</div>");
        $(container).append("<div class=‘loading-end‘>已经到底了</div>");

        $(container).find(".ys-scroll-content").append(childrenNode);

        $(container).scrollTop(LOADING_BAR_HEIGHT);

        $(container).data("settings",settings);
        return container;
    }

    function bindEventHandlers(target,container,settings){

        var loadingTopRevertTimeout = null;
        var loadingTopEndTimeout = null;

        var loadingBottomRevertTimeout = null;
        var loadingBottomTimeout = null;

        var pulldownCallback = settings.pulldownCallback;
        var pullupCallback = settings.pullupCallback;

        function clearTimeouts(){
            clearTimeout(loadingTopRevertTimeout);
            clearTimeout(loadingTopEndTimeout);
            clearTimeout(loadingBottomRevertTimeout);
            clearTimeout(loadingBottomTimeout);
        }

        function scrollHandler(){
            clearTimeouts();

            var loadingTop = false;

            if(arriveLoadingTopStart(container)){
                loadingTopRevertTimeout = setTimeout(function(){
                    loadingTopRevert(container);
                },RESPONSE_DELAY);
                loadingTop = true;
            }

            if(arriveLoadingTopEnd(container)){
                clearTimeouts();

                loadingTopEndTimeout = setTimeout(function(){
                    resetLoading(container);
                    pulldownCallback();
                },RESPONSE_DELAY);
                loadingTop = true;
            }

            var hasArrivedEnd = $(container).data("settings").hasArrivedEnd;
            if(hasArrivedEnd||loadingTop){ // 如果已经到底了不需要额外操作
                return;
            }

            if(arriveLoadingBottomStart(container)){
                loadingBottomRevertTimeout = setTimeout(function(){
                    loadingBottomRevert(container);
                },RESPONSE_DELAY);
            }

            if(arriveLoadingBottomEnd(container)){
                clearTimeouts();

                loadingBottomTimeout = setTimeout(function(){
                    pullupCallback();
                },RESPONSE_DELAY)
            }
        }

        var hasPressed = false;
        $(container).on("touchstart",function(event){
            hasPressed = true;
            clearTimeouts();
            stopAnimation(container);
        });

        $(container).on("touchmove",function(event){

            hasPressed = true;
            clearTimeouts();
            stopAnimation(container);

            var clientX = event.originalEvent.changedTouches[0].clientX;
            var clientY = event.originalEvent.changedTouches[0].clientY;
            if(clientY<0||clientX<0){
                scrollHandler();
            }
        });

        $(container).on("touchend touchcancel",function(event){
            scrollHandler();
            hasPressed = false;
        });

        $(container).scroll(function(){
            if(hasPressed||reverting){
                return;
            }
            scrollHandler();
        });
    }

    var RESPONSE_DELAY = 800; // 触发延迟
    var ANIMATION_DURATION = 300; // 动画持续时间
    var LOADING_BAR_HEIGHT = 40; // loading bar 高度

    var reverting = false; // 动画正在恢复

    function stopAnimation(container){
        $(container).stop(true);
        reverting = false;
    }

    function loadingTopRevert(container){
        reverting = true;
        $(container).animate({
            "scrollTop":LOADING_BAR_HEIGHT+"px"
        },ANIMATION_DURATION,function(){
            reverting = false;
        });
    }

    /* 判断达到 Loading-top开始处 */
    function arriveLoadingTopStart(container){
        var scrollTop = $(container).scrollTop();
        if(scrollTop<LOADING_BAR_HEIGHT){
            return true;
        }
        return false;
    }

    /* 判断达到 Loading-top结束处 */
    function arriveLoadingTopEnd(container){
        var scrollTop = $(container).scrollTop();

        if (scrollTop<1) {
            return true;
        }
        return false;
    }

    function loadingBottomRevert(container){
        reverting = true;
        var clientHeight = $(container).height();
        var scrollTop = $(container)[0].scrollHeight-LOADING_BAR_HEIGHT-clientHeight;
        $(container).animate({
            "scrollTop":scrollTop+"px"
        },ANIMATION_DURATION,function(){
            reverting = false;
        });

    }

    /* 判断到达 Loading Bottom 开始处 */
    function arriveLoadingBottomStart(container){
        var scrollTop = $(container).scrollTop();
        var scrollHeight = $(container)[0].scrollHeight;
        var clientHeight = $(container).height();

        if (scrollTop + clientHeight+LOADING_BAR_HEIGHT>= scrollHeight) {
            return true;
        }
        return false;
    }

    /* 判断到达 Loading Bottom 结束处 */
    function arriveLoadingBottomEnd(container){
        var scrollTop = $(container).scrollTop();
        var scrollHeight = $(container)[0].scrollHeight;
        var clientHeight = $(container).height();
        if (scrollTop + clientHeight+1> scrollHeight) {
            return true;
        }
        return false;
    }

    /* 重设 loading */
    function resetLoading(container){
        $(container).data("settings").hasArrivedEnd=false;
        $(container).find(".loading-bottom").show();
        $(container).find(".loading-end").hide();
    }

    /* 设置loading end */
    function setLoadingEnd(container){
        $(container).data("settings").hasArrivedEnd=true;
        $(container).find(".loading-bottom").hide();
        $(container).find(".loading-end").show();
    }

    var options = {
        ysScroll:function(settings) {
            var mergedSettings = {};
            $.extend(mergedSettings,defaultSettings,settings);

            $(this).each(function(){
                var container = render(this,settings);
                $(container).data("settings",settings);
                bindEventHandlers(this,container,mergedSettings);
            });
        },
        ysScrollRefresh:function(){
            if(arriveLoadingTopStart(this)){
                loadingTopRevert(this);
            }

            if(arriveLoadingBottomStart(this)){
                loadingBottomRevert(this);
            }
        },

        ysScrollLoadEnd:function(){
            setLoadingEnd(this);
        }
    };
    $.fn.extend(options);
})(jQuery);

测试页面 scroll.html

<!DOCTYPE html>
<!--[if lt IE 7]>      <html class="no-js lt-ie9 lt-ie8 lt-ie7"> <![endif]-->
<!--[if IE 7]>         <html class="no-js lt-ie9 lt-ie8"> <![endif]-->
<!--[if IE 8]>         <html class="no-js lt-ie9"> <![endif]-->
<!--[if gt IE 8]><!--> <html class="no-js"> <!--<![endif]-->
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
    <title></title>
    <meta name="description" content="">
    <meta name="viewport" content="width=device-width, initial-scale=1,minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
    <meta name="format-detection" content="telephone=no">
    <link href="css/common/ys_scroll.css" rel="stylesheet">
    <style>
        html,body,.container{
            height:100%;
            margin:0;
            padding:0;
        }
    </style>
</head>
<body>
<div class="container">
    <ul>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
        <li>这是测试数据...</li>
    </ul>
</div>

<script src="dist/js/jquery-1.11.3.min.js"></script>
<script src="js/common/ys_scroll.js"></script>

<script>
    var dataHtml = $(".container ul").html();

    $(".container ").ysScroll({
        pulldownCallback:function(){ // 下拉回调
            console.log("pull down ... ");

            $(".container ul").html(dataHtml);
            $(".container ").ysScrollRefresh();
        },
        pullupCallback:function(){ // 上拉回调
            console.log("pull up ... ");
            $(".container  ul").append(dataHtml);
            $(".container ").ysScrollRefresh();
        }
    });
</script>
</body>
</html>

注:容器使用前要给其设置一个固定的高度。当触发pulldownCallback,pullupCallback回调后一定要使用$(".container").ysScrollRefresh();重置容器。

时间: 2024-12-29 23:50:16

hml5 自定义滑动控件的相关文章

Android 结合滑动控件ListView滑动删除

一转眼就15年了,希望大家15年升职加薪走上人生巅峰 这篇博客是结合上一篇ListView滑动删除之Viewgroup打造滑动控件(修正版)博客所完成的,先上个效果图吧. 其实实现起来并不复杂 1,解决滑动冲突 因为我们的自定义滑动控件和ListView本身的滑动事件会产生各种冲突,所以我们可以自定义ListView并重写onInterceptTouchEvent方法. 我们先来了解一下android事件的分发,当用户触摸屏幕时会先去调用ViewGroup的dispatchTouchEvent方

Android自定义LinearLayout实现左右侧滑菜单,完美兼容ListView、ScrollView、ViewPager等滑动控件

国际惯例,先来效果图 在阅读本文章之前,请确定熟悉[Scroller]相关的知识,如果不熟悉,请小伙伴儿先百度后再来吧. 假如你已经知道[Scroller]了,那么就接着往下看吧. 首先,我们把侧拉菜单的构造给解析出来.多次观看上面的效果图,我们可以得出以下的结论. 整体可以看做是一个ViewGroup,这个ViewGroup包含了最多三个子View(分别是左菜单的红色View.中间正文内容的白色View.右菜单的蓝色View): 三个子View(我称为UI界面,因为代码中的Java类就取名这个

Android 实现 IOS相机滑动控件

 IOS相比于Android,动画效果是一方面优势,IOS相机切换时滑动的动画很不错,看着是有一个3D的效果,而且变化感觉很自然.Android也可以通过Graphics下面的Camera可以实现3D效果,开始尝试着用这个做了一下,效果不理想,滑动之后各组文字之间的距离就变了,从立体空间来说这是合逻辑的,但是看着很别捏.IOS相机的滑动效果文字之间的间隔在滑动的时候是不变的. 后面通过调整TextView X方向的scale使文字看着紧凑一点,然后通过计算的距离的方式,在滑动的时候保持各组文字之

iOS中的UIScorllView(滑动控件,时机控制)的基本使用

#import "RootViewController.h" #define kScreenWidth [UIScreen mainScreen].bounds.size.width #define kScreenHeight [UIScreen mainScreen].bounds.size.height @interface RootViewController () <UIScrollViewDelegate> @end @implementation RootVie

Android嵌套滑动控件的冲突解决和ViewPager适配当前子控件高度不留空白的办法

最近项目有一个需求,需要多层可滑动控件的嵌套展示,demo效果如下,demo的下载地址在最后 咋一看好像挺简单啊,不就是一个ScrollView + ViewPager + ListView吗,我开始也这样觉得,也用的这种方式实现,结果始终和效果不对劲.这里总结几点问题: 两个或两个以上的滑动控件嵌套时,如果layout_height采用的是wrap_content会造成内部滑动控件的高度不能正确的计算,会导致内部滑动控件的高度始终为0,除非你用定值设置,比如300dp. 两个相同滑动方向的滑动

自定义日历控件-CalendarView

转载请注明出处: http://blog.csdn.net/forwardyzk/article/details/43056675 我们在开发中会遇到使用到日历控件,下面就介绍一个自定义日历控件. 思路: 1.自定义类CalendarView继承LinearLayout,使用布局文件,显示布局. 2.使用ViewFlipper,里面添加GridView,当月的日期. 3.使用手势GestureDetector,控制ViewFlipper的滑动. calen_calendar.xml <span

自定义Gallery控件实现简单3D图片浏览器

本篇文章主要介绍如何使用自定义的Gallery控件,实现3D效果的图片浏览器的效果. 话不多说,先看效果. 上面是一个自定义的Gallery控件,实现倒影和仿3D的效果,下面是一个图片查看器,点击上面的小图片,可以在下面查看大图片. 下面重点说一下,实现图片查看器的思路. 1.手机中图片路径的获取 首先,先不管图片如何展示,如果我们想实现图片查看器的功能,我们首先需要做的是获取到所有的图片的路径信息,只有这样,我们才能实现对图片的查看. 我们可以使用下面的代码实现 private List<St

小米3系统计算器自定义开关控件-MySwitchView

1.前言 在android4.0以后,有switch控件,类似于iPhone上面滑块的效果,但是只能用在4.0以后的系统中,之前的平台,就无法使用这种控件.近段时间,看到了小米3手机上自带的计算器app,有这样的效果,上面的一个控件,觉得很漂亮,并且与iPhone上的效果略有不同,于是自己动手编写了一下这个功能,在编写的过程中,参考过网上的一些demo,运行后,在控件滑动的时候,感觉动画不平滑,有卡顿的现象,反复修改,最后还是有一些问题,感觉是在滑动中的状态,没有合理的控制好.无奈只能参考Goo

Android实现图片轮显效果——自定义ViewPager控件

一.问题概述 使用ViewPager控件实现可横向翻页.水平切换图片等效果,但ViewPager需要手动滑动才能切换页面,图片轮显效果的效果本质上就是在ViewPager控件的基础上让它能自动的进行切换,所以实现图片轮显步骤如下: 1.  扩展ViewPager自定义一个MyScrollImageView类 2.  为MyScrollImageView定义适配器,装载图片信息 3.  定义图片滑动动画时间控制类 接下来我们就一步步实现下图案例: 二.实现套路 1.为自定义ViewPager控件编