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,希望大家提出优化的意见