美文网首页iOS军械库iOS点滴
一行代码实现headView弹簧拉伸效果

一行代码实现headView弹簧拉伸效果

作者: findM | 来源:发表于2015-12-02 02:07 被阅读2678次
blog_demo.gif

前言

很多app的个人中心上部的headView都实现了弹簧拉伸的效果,即tableView的top并不随着下拉而滑动,而是紧紧的停在屏幕的最上方。
我们今天就分析一下这个效果的实现方式。


分析

blog1_spec.png

关键代码

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.tableView];
    
    self.headView.bounds = CGRectMake(0, 0, self.tableView.bounds.size.width, 200);
    self.tableView.tableHeaderView = self.headView;
    self.topImageView.frame = self.headView.bounds;
    [self.headView addSubview:self.topImageView];
    
    //在viewDidLoad方法中记录原始的y和height
    self.originY = self.topImageView.y;
    self.originHeight = self.topImageView.height;
}


#pragma mark - UIScrollViewDelegate
- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGFloat offy = scrollView.contentOffset.y;
    if (offy < 0) {
        self.topImageView.y = offy;
        self.topImageView.height = self.originHeight - offy;
    }else{
        self.topImageView.y = self.originY;
        self.topImageView.height = self.originHeight;
    }
}

ok,到此你已经实现了headView的弹簧效果了!

多想一步,进一步优化

虽然上面已经实现了功能所需,但是这个效果的代码跟项目耦合在一起的,不能复用。每次实现这个效果,都要写一遍上面的代码。不能忍啊,我们进一步优化!

我们创建一个名为UIScrollView+SpringHeadView.h的UIScrollView的分类

UIScrollView+SpringHeadView类中的实现方法如下

//UIScrollView+SpringHeadView.h的内容
#import <UIKit/UIKit.h>
//headView 的高度
#define SpringHeadViewHeight 200

@interface UIScrollView (SpringHeadView)<UIScrollViewDelegate>
//在分类增加了属性,这个是利用runtime实现的
@property (nonatomic, weak) UIView *topView;
- (void)addSpringHeadView:(UIView *)view;
@end
//UIScrollView+SpringHeadView.m的内容
- (void)setTopView:(UIView *)topView{
    [self willChangeValueForKey:@"SpringHeadView"];
    objc_setAssociatedObject(self, &UIScrollViewSpringHeadView,
                             topView,
                             OBJC_ASSOCIATION_ASSIGN);
    [self didChangeValueForKey:@"SpringHeadView"];
}

- (UIView *)topView{
    return objc_getAssociatedObject(self, &UIScrollViewSpringHeadView);
}


- (void)addSpringHeadView:(UIView *)view{
    self.contentInset = UIEdgeInsetsMake(view.bounds.size.height, 0, 0, 0);
    [self addSubview:view];
    view.frame = CGRectMake(0, -view.bounds.size.height, view.bounds.size.width, view.bounds.size.height);
    self.topView = view;
    //使用kvo监听scrollView的滚动
    [self addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    [self scrollViewDidScroll:self];
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView{
    CGFloat offy = scrollView.contentOffset.y;
    
    if (offy < 0) {
        self.topView.frame = CGRectMake(0, offy, self.topView.bounds.size.width, -offy);
    }
}

现在我们使用起来爽了,只要需要引入UIScrollView+SpringHeadView.h,一行代码就能实现弹簧的效果啦!

//引入分类
#import "UIScrollView+SpringHeadView.h"

- (void)viewDidLoad {
    [super viewDidLoad];
    [self.view addSubview:self.tableView];
    
    self.topImageView.frame = CGRectMake(0, 0, self.tableView.bounds.size.width, SpringHeadViewHeight);
    //只需要一行代码,就能实现同样效果
    [self.tableView addSpringHeadView:self.topImageView];
}

获取完整的代码点我

相关文章

网友评论

  • 思念那年慕云:界面二次进入的时候就会崩溃,
    reason: 'An instance 0x7fd3f48a5a00 of class UITableView was deallocated while key value observers were still registered with it. Current observation info: <NSKeyValueObservationInfo 0x7fd3f6606ee0> (
    <NSKeyValueObservance 0x7fd3f6606e80: Observer: 0x7fd3f48a5a00, Key path: contentOffset, Options: <New: YES, Old: NO, Prior: NO> Context: 0x0, Property: 0x7fd3f657fcb0>
  • 我不是杰迷:非常感谢
  • wwwbbat:没什么卵用。你把scrollView的delegate设置了。让在其他地方需要设置代理的时候怎么办呢? 这样写是很不靠谱的。
    findM:已修正
    findM:@Voyager3 有道理,没考虑周全,马上改!
    wwwbbat:@Voyager3 建议在category里创建一个辅助类,用KVO来监听contentOffset。
  • 曾樑:挺有用的
  • 篮球火:很给力,实战必备经验

本文标题:一行代码实现headView弹簧拉伸效果

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