0 最近因?yàn)轫?xiàng)目的原因需要實(shí)現(xiàn)微博多tablview上下拉升的特效考婴,所以在網(wǎng)上找了個(gè)框架:AXStretchableHeaderTabViewController?龄糊,
具體實(shí)現(xiàn)效果如下
在使用這個(gè)框架的時(shí)候是個(gè)很蛋疼的過程
1枪萄、必須要先計(jì)算出頭部綠色視圖的高度,才能創(chuàng)建頭部視圖和下面兩個(gè)ViewController,否則上下拉伸會(huì)有問題
后來仔細(xì)閱讀了這個(gè)框架的源碼后苇瓣,我就自己寫了一個(gè)LPPZStretchViewController捷沸,精簡(jiǎn)了很多代碼,而且在使用更加便捷
實(shí)現(xiàn)的思路
1厂财、在LPPZStretchViewController中芋簿,先創(chuàng)建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、然后再創(chuàng)建繼承自LPPZStretchHeaderView的header璃饱,(在LPPZStretchHeaderView中會(huì)有一些其他的處理与斤,主要是關(guān)于事件傳遞的處理,在文章的最后我會(huì)寫)
? ? _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可拉伸的最大長(zhǎng)度??
? ? ? ? ? 2、self.MinHeaderViewHeight是headerView可拉伸的最短長(zhǎng)度
3裆甩、然后在創(chuàng)建中間黃色的類別條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、然后這創(chuàng)建自定義的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是設(shè)置tableView的頭部邊距,
? ? ? ? CGFloat y = KtabBarHeigh + self.MaxHeaderViewHeight;
? ? ? ? [self addChildViewController:vc1];
? ? ? ? [self.mainScrollView addSubview:vc1.view];
? ? ? ? UITableView* tableView? = [vc1 valueForKey:@"tableView"];
//監(jiān)聽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"];
//監(jiān)聽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、監(jiān)聽tableview的偏移量锭弊,重新設(shè)置headerView的高度堪澎,以及ListViewController在mainScrollView的frame
-(void)observeValueForKeyPath:(NSString*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void*)context{
? ? if([keyPathisEqualToString:@"contentOffset"]) {
//計(jì)算tableView向上滑動(dòng)的距離,從而設(shè)置headView的高度味滞,當(dāng)headView高度變短時(shí)樱蛤,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);
? ? }
}
結(jié)尾:在LPPZStretchHeaderView需要重寫- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event方法
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event{
? ? UIView* targetView = [superhitTest:pointwithEvent:event];
//當(dāng)相應(yīng)事件點(diǎn)擊的View是LPPZStretchHeaderView是剑鞍,則返回nil昨凡,這樣根據(jù)iOS事件傳遞的機(jī)制,事件會(huì)傳遞給LPPZStretchHeaderView的下面的mainScrollView蚁署,這樣手機(jī)放在LPPZStretchHeaderView上也可以做到上下互動(dòng)的效果
? ? if(targetView ==self) {
? ? ? ? returnnil;
? ? }
? ?if(targetView.userInteractionEnabled==YES) {
? ? ? ? NSLog(@"123godlike");
? ? ? ? returntargetView;
? ? }
關(guān)于LPPZStretchViewControllerd便脊,我已經(jīng)上傳到了github上,LPPZStretchViewController光戈,希望大家提出優(yōu)化的意見