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了

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

相关文章推荐

ionic3/ag4编写模仿京东商城的demo

ionic3angular4JD使用1.cnpm install或者使用npm install2.ionic serve3有需要使用android/ios平台 ionic platform add...

IONIC键盘弹出防止页面Header(title位置)自动上移位置(消失)

近两年由于html5技术的普及,混合类应用在移动市场占据了大量的份额,但是如果想用html5技术达到native的效果,还需要一点努力的。比如在混合应用中,当页面空间不是很足的时候,点击输入框弹出键盘...

ionic的侧滑和下拉刷新效果

一,侧滑效果 主要涉及到三个地方 1,菜单页面 主要分为主页面和侧滑页面两部分,又分别都包含顶部bar和主要内容部分 注意:主页面内容部分,关键的菜单内容name要对应到是菜单内容的页面(在app.j...

移动端html5页面长按实现高亮全选文本内容的兼容解决方案

最近需要给html5的WebAPP在页面上实现一个复制功能:用户点击长按文本会全选文字并弹出系统“复制”菜单,用户可以点击“复制”进行复制操作,然后粘贴到AppStore搜索对应的应用。之所以不是采用...

iOS 实现时间线列表效果

iOS 实现时间线列表效果

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

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

iOS 实现时间线列表效果

本文授权转载,作者:Cyandev  之前看到美团的订单详情页面很有特色,于是决定模仿一下这个效果。 其实就是简单的 TableView 技巧,下面我们就来一步一步实现它。 ...

iOS 实现时间线列表效果

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

iOS 列表折叠效果

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

高仿新百度贴吧列表效果

  • 2014-02-27 16:38
  • 1.49MB
  • 下载
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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