关于多tablview上下拉升的效果实现

0 最近因为项目的原因需要实现微博多tablview上下拉升的特效,所以在网上找了个框架:AXStretchableHeaderTabViewController ,

具体实现效果如下

在使用这个框架的时候是个很蛋疼的过程

1、必须要先计算出头部绿色视图的高度,才能创建头部视图和下面两个ViewController,否则上下拉伸会有问题

后来仔细阅读了这个框架的源码后,我就自己写了一个LPPZStretchViewController,精简了很多代码,而且在使用更加便捷

实现的思路


1、在LPPZStretchViewController中,先创建UIScrollView*mainScrollView

  self.mainScrollView =({

        UIScrollView* mainScrollView = [[UIScrollViewalloc]init];

        mainScrollView.delegate=self;

        mainScrollView.backgroundColor = [UIColor yellowColor];

        [self.view addSubview:mainScrollView];

        mainScrollView.pagingEnabled=YES;

        mainScrollView.contentSize=CGSizeMake(UI_SCREEN_WIDTH*2,0);

        mainScrollView.frame=CGRectMake(0,0,UI_SCREEN_WIDTH,UI_SCREEN_HEIGHT);

        mainScrollView;

    });

2、然后再创建继承自LPPZStretchHeaderView的header,(在LPPZStretchHeaderView中会有一些其他的处理,主要是关于事件传递的处理,在文章的最后我会写)

    _headerView = [[LPPZStretchHeaderView alloc] init];

//重要的地方。_headerView不是添加到mainScrollView上哦

    [self.view addSubview:_headerView];

    _headerView.backgroundColor = [UIColor greenColor];

    [_headerView mas_makeConstraints:^(MASConstraintMaker *make) {

        make.left.top.right.equalTo(self.view);

        self.headerViewHeightConstraint=  make.height.mas_equalTo(self.MaxHeaderViewHeight);

    }];


注意:1、self.MaxHeaderViewHeight是headerView可拉伸的最大长度  

          2、self.MinHeaderViewHeight是headerView可拉伸的最短长度

3、然后在创建中间黄色的类别条LPPZStretchTabBarView

 self.tabBarView = ({

        LPPZStretchTabBarView *tabBarView = [[LPPZStretchTabBarView alloc] init];

        [self.viewaddSubview:tabBarView];

        tabBarView.backgroundColor = [UIColor yellowColor];

        tabBarView.titles=@[@"精选",@"热门"];

        [tabBarViewmas_makeConstraints:^(MASConstraintMaker *make) {

            make.left.right.equalTo(self.view);

            make.height.mas_equalTo(KtabBarHeigh);

            make.top.equalTo(self.headerView.mas_bottom);

        }];

        tabBarView;

    });



4、然后这创建自定义的LPPZListViewController,并且LPPZListViewController包含有属性tableView的UITableView    ,主要是方便取出LPPZListViewController中的tableView,LPPZListViewController的视图是在mainScrollView伤的

    LPPZListViewController * vc1 = [[LPPZListViewController alloc] init];

    LPPZListViewController * vc2 = [[LPPZListViewController alloc] init];

       NSIndexPath * indexPath = [NSIndexPath indexPathForRow:0 inSection:0];


//y是设置tableView的头部边距,

        CGFloat y = KtabBarHeigh + self.MaxHeaderViewHeight;


        [self addChildViewController:vc1];

        [self.mainScrollView addSubview:vc1.view];

        UITableView* tableView  = [vc1 valueForKey:@"tableView"];

//监听tableView的偏移量的变化,

        [tableView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];

        vc1.view.frame = CGRectMake(0 *UI_SCREEN_WIDTH, 0,UI_SCREEN_WIDTH,UI_SCREEN_HEIGHT);

        tableView.contentInset=UIEdgeInsetsMake(y,0,0,0);

        [tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];



[self addChildViewController:vc2];

        [self.mainScrollViewaddSubview:vc2.view];

UITableView* tableView2  = [vc2 valueForKey:@"tableView"];

//监听tableView的偏移量的变化,

        [tableView2 addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];

 vc2.view.frame = CGRectMake(0 *UI_SCREEN_WIDTH, 0,UI_SCREEN_WIDTH,UI_SCREEN_HEIGHT);

        tableView2.contentInset=UIEdgeInsetsMake(y,0,0,0);

        [tableView2 scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:NO];


5、监听tableview的偏移量,重新设置headerView的高度,以及ListViewController在mainScrollView的frame

-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context{

    if([keyPathisEqualToString:@"contentOffset"]) {

//计算tableView向上滑动的距离,从而设置headView的高度,当headView高度变短时,headView遮盖tableView的高度也就小了,

        CGFloat headerViewHeight = self.MaxHeaderViewHeight - (self.selectedScrollView.contentOffset.y + self.selectedScrollView.contentInset.top) -20;

//headView的高度不能小于self.MinHeaderViewHeight

        if(headerViewHeight <=self.MinHeaderViewHeight) {

            headerViewHeight =self.MinHeaderViewHeight;

        }

        self.headerViewHeightConstraint.mas_equalTo(headerViewHeight);

        !self.headerViewHeightChangeBlock ?: self.headerViewHeightChangeBlock(headerViewHeight);

    }

}


结尾:在LPPZStretchHeaderView需要重写- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event方法


- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{

    UIView* targetView = [superhitTest:pointwithEvent:event];

//当相应事件点击的View是LPPZStretchHeaderView是,则返回nil,这样根据iOS事件传递的机制,事件会传递给LPPZStretchHeaderView的下面的mainScrollView,这样手机放在LPPZStretchHeaderView上也可以做到上下互动的效果

    if(targetView ==self) {

        returnnil;

    }

   if(targetView.userInteractionEnabled==YES) {

        NSLog(@"123godlike");

        returntargetView;

    }


关于LPPZStretchViewControllerd,我已经上传到了github上,LPPZStretchViewController,希望大家提出优化的意见

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 因为之前开发时都是在xib文件中添加约束,或者代码中计算frame并没有接触过Masonry,现在写篇博客来归纳总...
    口子窖阅读 11,560评论 1 4
  • *Masonry有哪些属性 @property (nonatomic, strong, readonly) MAS...
    Albert新荣阅读 2,463评论 0 0
  • iOS_autoLayout_Masonry 概述 Masonry是一个轻量级的布局框架与更好的包装AutoLay...
    指尖的跳动阅读 4,941评论 1 4
  • (一)Masonry介绍 Masonry是一个轻量级的布局框架 拥有自己的描述语法 采用更优雅的链式语法封装自动布...
    木易林1阅读 7,044评论 0 3
  • Masonry是一个轻量级的布局框架,拥有自己的描述语法,采用更优雅的链式语法封装自动布局,简洁明了并具有高可读性...
    3dcc6cf93bb5阅读 5,811评论 0 1