印象笔记交互效果的实现

作者: allsome | 来源:发表于2015-11-03 20:11 被阅读6430次
    啰嗦几句

    起初我是想把这个demo做的和原版一摸一样,但在印象笔记的ipa中并没有找到那些关键的图片,网上也没有相关的素材,而且当我在百度搜索里面赫然敲下印象笔记四个大字的时候,百度搜索竟然给我推荐印象笔记面临倒闭这样的关键字!好吧,在当下新技术大潮一波接一波的年代,这种被面临倒闭的公司还有很多,但我个人感情上希望那一天能来的晚一些,反倒是些世界500强,民族企业之类的,我由衷的希望他明天就关门。我也斗胆尝试过用sketch画出所有的切图,但当我画完一个️后就彻底放弃了这个想法,索性也就弄成现在这个样子。

    不夸张的说我半路转来做ios和印象笔记这两个交互效果是有很大关系的,在没有作出这个demo之前,我对evernote的这两个交互效果特别的着迷,而在我转做ios之后,这种感觉反而更加强烈了,因为凭我当时那点浅薄的ios经验,完全不知道这个效果是怎么做到的,我也像疯子一样在各种code网站疯狂扫荡一遍也没有找到相应的demo,趁着这段时间比较闲就把它实现了。

    弹簧效果:
    弹簧.gif

    使用collectionView,自定义布局继承UICollectionViewFlowLayout,想要这些cell按照我们的意思动起来,首先重写shouldInvalidateLayoutFor
    BoundsChange
    返回true。

     override func shouldInvalidateLayoutForBoundsChange(newBounds: CGRect) -> Bool {
            return true
     }
    

    这个动画只在collectionview滑动到顶部和底部会触发,重写layoutAttributesForElementsInRect这个方法根据collectionviewcontentoffset计算出cellframe,这样就ok了。

    override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
            let offsetY = self.collectionView!.contentOffset.y
            let attrsArray = super.layoutAttributesForElementsInRect(rect)
            let collectionViewFrameHeight = self.collectionView!.frame.size.height;
            let collectionViewContentHeight = self.collectionView!.contentSize.height;
            let ScrollViewContentInsetBottom = self.collectionView!.contentInset.bottom;
            let bottomOffset = offsetY + collectionViewFrameHeight - collectionViewContentHeight - ScrollViewContentInsetBottom
            let numOfItems = self.collectionView!.numberOfSections()
            
            for attr:UICollectionViewLayoutAttributes in attrsArray! {
                if (attr.representedElementCategory == UICollectionElementCategory.Cell) {
                    var cellRect = attr.frame;
                    if offsetY <= 0 {
                        let distance = fabs(offsetY) / SpringFactor;
                        cellRect.origin.y += offsetY + distance * CGFloat(attr.indexPath.section + 1);
                    }else if bottomOffset > 0 {
                        let distance = bottomOffset / SpringFactor;
                        cellRect.origin.y += bottomOffset - distance *
                            CGFloat(numOfItems - attr.indexPath.section)
                    }
                    attr.frame = cellRect;
                }
            }
            return attrsArray;
     }
    
    转场效果:
    转场效果.gif

    自定义类EvernoteTransition遵守UIViewControllerAnimated TransitioningUIViewControllerTransitioningDelegate
    该类的对象作为transitioningDelegate。实现
    UIViewControllerAnimatedTransitioning
    transitionDurationanimateTransition方法前者返回动画的时间,后者用来实现转场时的具体动画。
    UIViewControllerTransitioningDelegatepresentdismiss代理方法中返回EvernoteTransition对象,这样就ok了

    func animationControllerForPresentedController(presented: UIViewController, presentingController presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            self.isPresent = true
            return self
    }
        
    func animationControllerForDismissedController(dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? {
            self.isPresent = false
            return self
    }
    
    手势互动:
    手势互动.gif
    实现UIViewControllerTransitioningDelegate
    interactionControllerForDismissal
    func interactionControllerForDismissal(animator: UIViewControllerAnimatedTransitioning) -> UIViewControllerInteractiveTransitioning? {
            self.isPresent = false
            return interactionController
    }
    

    给第二个controller加上一个UIScreenEdgePanGestureRecognizer手势方向为left,实时的更新interactionController,这样就ok了.

    func handlePanGesture(recognizer:UIScreenEdgePanGestureRecognizer) {
            let view = panViewController.view
            if recognizer.state == UIGestureRecognizerState.Began {
                panViewController.dismissViewControllerAnimated(true, completion: { () -> Void in
                })
            } else if recognizer.state == UIGestureRecognizerState.Changed {
                let translation = recognizer.translationInView(view)
                let d = fabs(translation.x / CGRectGetWidth(view.bounds))
                interactionController.updateInteractiveTransition(d)
            } else if recognizer.state == UIGestureRecognizerState.Ended {
                if recognizer.velocityInView(view).x > 0 {
                    interactionController.finishInteractiveTransition()
                } else {
                    interactionController.cancelInteractiveTransition()
                    listViewController.presentViewController(panViewController, animated: false, completion: { () -> Void in
                        
                    })
                }
                interactionController = UIPercentDrivenInteractiveTransition()
            }
    }
    
    具体源码:

    ** GitHub**
    ** Bitbucket**

    注:在我自认为没有任何商业意图的前提下,从dribbble上面搬来了第一张GIF,如果这篇文章有幸被原制作者看到并且认为我这种做法给他带来了困扰,我便立即删除,最后送大家一首克罗地亚狂想曲

    如果您发现文中有任何不妥之处,还望不吝赐教!

    相关文章

      网友评论

      • 苦笑男神:运行之后,发现有报错,但是不影响运行,我怀疑是改变cell 的 frame的时机不恰当引起的,博主检查一下呗,错误信息:
        Logging only once for UICollectionViewFlowLayout cache mismatched frame
        This is likely occurring because the flow layout subclass HWCollectionViewFlowLayout is modifying attributes returned by UICollectionViewFlowLayout without copying them
      • _锋:很棒:+1:
      • NeiL978:很棒的效果^_^
      • 2e0084e1e76a:你好,我想问下cell的那个弹簧效果是重写layoutAttributesForElementsInRect实现的对么?我对着你的swift用OC写了一遍 但是无法实现弹簧效果 我已经shouldInvalidateLayoutForBoundsChange 返回true 还有什么注意点么?
        allsome:@梦断oo花都 oraclelsy@163.com
        2e0084e1e76a:@allsome 好的 给个联系方式呗
        allsome:@梦断oo花都 把代码发我看下吧
      • oriyum:谢谢分享。
        我想问下gif格式怎么显示在文章里面的,我写文章时候gif显示不了
        allsome:@BrandonYum markdown模式下,直接把GIF拖进来即可。
      • UASHS:好文,绝对干货,赞一个,望博主继续写下去,会一直关注的
      • NSJoe:一直想找的
      • Amelie槿岩:awsome:+1:
        allsome:@超人妹槿岩 😳
      • 瑞廷:不错
      • 韩大熊宝要姓张:谢谢分享.加油.我也很喜欢这个效果.
        allsome:@韩大熊宝要姓张 共勉
      • 210dad6f4cd2:我也很喜欢印象笔记的交互效果,一直以为只用CA动画就能实现,看了本文才知道有如此方法好用的方法,我也刚刚iOS开发,swift暂时没学,不过方法都是一样,很受用!
        fcb856a4cf0e:@銘心 你好,你用OC做出来了吗,求demo,我转oc没有做出来呢,求指点 :heart_eyes:
      • 聪聪:不错,赞一个! :+1:
      • Matcha00:好好好
      • 530bdfd8f56c:牛逼阿。
      • 印林泉:大神!我是因为随手记开始做iOS,好几年了,今年终于毕业全职做iOS,虽然开始工资不高~
        allsome:@印林泉 加油
      • 奔跑的小菜菜:作者iOS多久了哈
        allsome:@Lis_iOS_Dev 去年这个时候下载的xcode
      • 求愚:Cool 请问手机的录屏软件是什么?
        allsome:@野子Joey 就是OSX自带的视频播放器啊
        求愚:@allsome 不好意思 在 app store 没搜到,全名是这个吗?logo是什么颜色的,thx
        allsome:@野子Joey quicktime player
      • 2990f789f13a:太棒了
      • 十一岁的加重:效果真漂亮,有tableView的demo吗
        allsome:@十一岁的加重 木有的,tableView不能这么灵活
      • allsome:看到的每一条评论和打赏也让我心动了好久,在此感谢你们的支持
      • d4713d91b2fc:让我心动了好久
      • ea9ae456d0de:这个动画,让我心动了好久
      • JanzTam:很棒!

      本文标题:印象笔记交互效果的实现

      本文链接:https://www.haomeiwen.com/subject/kgbqhttx.html