IONIC高仿IOS 列表Title粘贴效果(IOS系统默认组列表效果)

原创 2016年08月30日 09:35:51

最近有一个需求要高仿IOS上的一个列表效果,比如当前有一个分组列表,当用户向上滚动,需要Group title保持在页面上方,粘贴住,不消失,当下一组滚动上来时,上一个title滚动到上方,下一个title粘贴在这个位置。

由于项目中用到了IONIC,所以编写了一个directive对此,参考affix库, 上代码:

'use strict';

// @ngInject
module.exports = function ($ionicPosition, $compile) {

        // keeping the Ionic specific stuff separated so that they can be changed and used within an other context

        // see https://api.jquery.com/closest/ and http://ionicframework.com/docs/api/utility/ionic.DomUtil/
        function getParentWithClass(elementSelector, parentClass) {
            return angular.element(ionic.DomUtil.getParentWithClass(elementSelector[0], parentClass));
        }

        // see http://underscorejs.org/#throttle
        function throttle(theFunction) {
            return ionic.Utils.throttle(theFunction);
        }

        // see http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
        // see http://ionicframework.com/docs/api/utility/ionic.DomUtil/
        function requestAnimationFrame(callback) {
            return ionic.requestAnimationFrame(callback);
        }

        // see https://api.jquery.com/offset/
        // see http://ionicframework.com/docs/api/service/$ionicPosition/
        function offset(elementSelector) {
            return $ionicPosition.offset(elementSelector);
        }

        // see https://api.jquery.com/position/
        // see http://ionicframework.com/docs/api/service/$ionicPosition/
        function position(elementSelector) {
            return $ionicPosition.position(elementSelector);
        }

        function applyTransform(element, transformString) {
            // do not apply the transformation if it is already applied
            if (element.style[ionic.CSS.TRANSFORM] == transformString) {
            }
            else {
                element.style[ionic.CSS.TRANSFORM] = transformString;
            }
        }

        function translateUp(element, dy, executeImmediately) {
            var translateDyPixelsUp = dy == 0 ? 'translate3d(0px, 0px, 0px)' : 'translate3d(0px, -' + dy + 'px, 0px)';
            // if immediate execution is requested, then just execute immediately
            // if not, execute in the animation frame.
            if (executeImmediately) {
                applyTransform(element, translateDyPixelsUp);
            }
            else {
                // see http://www.paulirish.com/2011/requestanimationframe-for-smart-animating/
                // see http://ionicframework.com/docs/api/utility/ionic.DomUtil/
                requestAnimationFrame(function () {
                    applyTransform(element, translateDyPixelsUp);
                });
            }
        }

        var CALCULATION_THROTTLE_MS = 500;

        return {
            // only allow adding this directive to elements as an attribute
            restrict: 'A',
            // we need $ionicScroll for adding the clone of affix element to the scroll container
            // $ionicScroll.element gives us that
            require: '^$ionicScroll',
            link: function ($scope, $element, $attr, $ionicScroll) {
                // get the affix's container. element will be affix for that container.
                // affix's container will be matched by "affix-within-parent-with-class" attribute.
                // if it is not provided, parent element will be assumed as the container
                var $container;
                if ($attr.affixWithinParentWithClass) {
                    $container = getParentWithClass($element, $attr.affixWithinParentWithClass);
                    if (!$container) {
                        $container = $element.parent();
                    }
                }
                else {
                    $container = $element.parent();
                }

                var scrollMin = 0;
                var scrollMax = 0;
                var scrollTransition = 0;
                // calculate the scroll limits for the affix element and the affix's container
                var calculateScrollLimits = function (scrollTop) {
                    var containerPosition = position($container);
                    var elementOffset = offset($element);

                    var containerTop = containerPosition.top;
                    var containerHeight = containerPosition.height;

                    var affixHeight = elementOffset.height;

                    scrollMin = scrollTop + containerTop;
                    scrollMax = scrollMin + containerHeight;
                    scrollTransition = scrollMax - affixHeight;
                };
                // throttled version of the same calculation
                var throttledCalculateScrollLimits = throttle(
                    calculateScrollLimits,
                    CALCULATION_THROTTLE_MS,
                    {trailing: false}
                );

                var affixClone = null;

                // creates the affix clone and adds it to DOM. by default it is put to top
                var createAffixClone = function () {
                    var clone = $element.clone().css({
                        position: 'absolute',
                        top: 0,
                        left: 0,
                        right: 0
                    });

                    // if directive is given an additional CSS class to apply to the clone, then apply it
                    if ($attr.affixClass) {
                        clone.addClass($attr.affixClass);
                    }

                    // remove the directive matching attribute from the clone, so that an affix is not created for the clone as well.
                    clone.removeAttr('ion-affix').removeAttr('data-ion-affix').removeAttr('x-ion-affix');

                    angular.element($ionicScroll.element).append(clone);

                    // compile the clone so that anything in it is in Angular lifecycle.
                    $compile(clone)($scope);

                    return clone;
                };

                // removes the affix clone from DOM. also deletes the reference to it in the memory.
                var removeAffixClone = function () {
                    if (affixClone)
                        affixClone.remove();
                    affixClone = null;
                };

                $scope.$on("$destroy", function () {
                    // 2 important things on destroy:
                    // remove the clone
                    // unbind the scroll listener
                    // see https://github.com/aliok/ion-affix/issues/1
                    removeAffixClone();
                    angular.element($ionicScroll.element).off('scroll');
                });


                angular.element($ionicScroll.element).on('scroll', function (event) {
                    var scrollTop = (event.detail || event.originalEvent && event.originalEvent.detail).scrollTop;
                    // when scroll to top, we should always execute the immediate calculation.
                    // this is because of some weird problem which is hard to describe.
                    // if you want to experiment, always use the throttled one and just click on the page
                    // you will see all affix elements stacked on top
                    if (scrollTop == 0) {
                        calculateScrollLimits(scrollTop);
                    }
                    else {
                        throttledCalculateScrollLimits(scrollTop);
                    }

                    // when we scrolled to the container, create the clone of element and place it on top
                    if (scrollTop >= scrollMin && scrollTop <= scrollMax) {

                        // we need to track if we created the clone just now
                        // that is important since normally we apply the transforms in the animation frame
                        // but, we need to apply the transform immediately when we add the element for the first time. otherwise it is too late!
                        var cloneCreatedJustNow = false;
                        if (!affixClone) {
                            affixClone = createAffixClone();
                            cloneCreatedJustNow = true;
                        }

                        // if we're reaching towards the end of the container, apply some nice translation to move up/down the clone
                        // but if we're reached already to the container and we're far away than the end, move clone to top
                        if (scrollTop > scrollTransition) {
                            translateUp(affixClone[0], Math.floor(scrollTop - scrollTransition), cloneCreatedJustNow);
                        } else {
                            translateUp(affixClone[0], 0, cloneCreatedJustNow);
                        }
                    } else {
                        removeAffixClone();
                    }
                });
            }
        }
    };

定义一个directive:

directive('ionAffix', /* */);

使用方法:

    <ion-list class="list-block" >
        <div id="list" class="item item-divider" ion-affix data-affix-within-parent-with-class="list">category</div>
        <ion-item>
        </ion-item>
    </ion-list>

这就ok了

版权声明:本文为博主原创文章,未经博主允许不得转载。

Ionic2 Sticky 粘附效果

ionic2中实现sticky功能,在ios中使用的是position:sticky属性,但是这个属性在大部分的浏览器中并不支持,android浏览器也一样不支持。在安卓中使用fixed属性。 我在...

ionic-轻触touch背景幕关闭popup弹出框

今天微信所谓的应用号“小程序”刷屏了,网上很多的技术人员都在讨论,微信整合了很多的web组件式功能提供给开发者,降低开发门槛,力求做到极致的原生体验和提高性能,很多人就担心,说看来微信要灭掉APP,一...

H5微信聊天案例、html5+css3仿微信聊天界面对话框 微信红包-打赏-霸屏

最新因项目需要,就利用HTML5+css3+jquery+weui做了一个仿微信聊天界面功能,可以发微信表情,查看图片、视频... ===HTML片段: ...

iOS 列表折叠效果

实现列表折叠效果其实比较简单,点击列表头部的时候,把返回列表行数设为 0,就是收起列表;再次点击列表头部,显示列表的行数,就展开了列表。#import "TableDownUpVC.h" #impor...

iOS 实现时间线列表效果

之前看到美团的订单详情页面很有特色,于是决定模仿一下这个效果。 其实就是简单的 TableView 技巧,下面我们就来一步一步实现它。 画个泡泡 首先到 Sketch 里画出气泡...

[笨笨的方法] 实现IOS列表的滑动删除效果

一、背景 在做项目的时候,有一个需求,在两级列表中,实现类似于IOS的滑动删除效果,大体如下图: 但有两点不太一样的地方:上层界面,是随手势滑动的;下层界面在上层被滑走后露出来。 ...

ios开发学习--列表(Table)效果源码分享--系列教程2

Static Content Table 介绍: 提供十分方便的静态内容列表(Static Content TableViewController)编写API。静态内容列表一般用于app的设置页...
  • apkbus
  • apkbus
  • 2012年12月16日 13:15
  • 817

IOS控件系列--滚动列表上下滑动时顶部视图固定与滑动效果(Swift版)

一,效果图: 二。状态分析: IOS这种滚动列表的滑动总共有四种状态(需要将弹性效果打开才有) 对于状态更新主要通过两个关键值判断: let offset : CG...

iOS 实现时间线列表效果

iOS 实现时间线列表效果

高仿新百度贴吧列表效果

  • 2014年02月27日 16:38
  • 1.49MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:IONIC高仿IOS 列表Title粘贴效果(IOS系统默认组列表效果)
举报原因:
原因补充:

(最多只允许输入30个字)