UITableView的headerView展开缩放动画
效果
源码
https://github.com/YouXianMing/Animations
// // HeaderViewTapAnimationController.m // Animations // // Created by FrankLiu on 15/11/30. // Copyright © 2015年 YouXianMing. All rights reserved. // #import "HeaderViewTapAnimationController.h" #import "ClassModel.h" #import "StudentInfoCell.h" #import "ClassHeaderView.h" #import "WxHxD.h" #import "GCD.h" static NSString *infoCellFlag = @"BaseTableViewCell"; static NSString *infoHeadFlag = @"ClassHeaderView"; @interface HeaderViewTapAnimationController () <UITableViewDataSource, UITableViewDelegate, CustomHeaderFooterViewDelegate> @property (nonatomic, strong) NSMutableArray *classModels; @property (nonatomic, strong) UITableView *tableView; @property (nonatomic) BOOL sectionFirstLoad; @property (nonatomic, weak) ClassHeaderView *tmpHeadView; @end @implementation HeaderViewTapAnimationController - (void)viewDidLoad { [super viewDidLoad]; } - (void)setup { [super setup]; [self createDatas]; [self createTableView]; [self bringTitleViewToFront]; [self firstLoadDataAnimation]; } #pragma mark - 数据源相关 - (void)createDatas { NSArray *datas = @[@{@"className" : @"Aitna", @"students" : @[@{@"name" : @"Y.X.M.", @"age" : @(27)}, @{@"name" : @"Leif", @"age" : @(12)}, @{@"name" : @"Lennon", @"age" : @(23)}, @{@"name" : @"Lambert", @"age" : @(19)}, @{@"name" : @"Jerome", @"age" : @(19)}, @{@"name" : @"Isidore", @"age" : @(19)}]}, @{@"className" : @"Melete", @"students" : @[@{@"name" : @"Merle", @"age" : @(34)}, @{@"name" : @"Paddy", @"age" : @(31)}, @{@"name" : @"Perry", @"age" : @(10)}, @{@"name" : @"Philip", @"age" : @(39)}]}, @{@"className" : @"Aoede", @"students" : @[@{@"name" : @"Verne", @"age" : @(34)}, @{@"name" : @"Vincent", @"age" : @(78)}, @{@"name" : @"Walter", @"age" : @(43)}, @{@"name" : @"Zachary", @"age" : @(21)}]}, @{@"className" : @"Dione", @"students" : @[@{@"name" : @"Timothy", @"age" : @(98)}, @{@"name" : @"Roderick", @"age" : @(21)}, @{@"name" : @"Quentin", @"age" : @(7)}, @{@"name" : @"Paddy", @"age" : @(67)}]}, @{@"className" : @"Adanos", @"students" : @[@{@"name" : @"Mortimer", @"age" : @(23)}, @{@"name" : @"Michael", @"age" : @(45)}, @{@"name" : @"Kevin", @"age" : @(89)}, @{@"name" : @"Jeremy", @"age" : @(23)}]},]; self.classModels = [[NSMutableArray alloc] init]; for (int count = 0; count < datas.count; count++) { ClassModel *classModel = [[ClassModel alloc] initWithDictionary:datas[count]]; classModel.expend = NO; [self.classModels addObject:classModel]; } } #pragma mark - tableView相关 - (UITableView *)createTableViewWithDelegate:(id)delegate frame:(CGRect)frame { UITableView *tableView = [[UITableView alloc] initWithFrame:frame style:UITableViewStylePlain]; tableView.delegate = delegate; tableView.dataSource = delegate; tableView.separatorStyle = UITableViewCellSeparatorStyleNone; tableView.showsHorizontalScrollIndicator = NO; tableView.showsVerticalScrollIndicator = NO; [tableView registerClass:[StudentInfoCell class] forCellReuseIdentifier:infoCellFlag]; [tableView registerClass:[ClassHeaderView class] forHeaderFooterViewReuseIdentifier:infoHeadFlag]; return tableView; } - (void)createTableView { self.tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, Width, Height - 64) style:UITableViewStylePlain]; self.tableView.delegate = self; self.tableView.dataSource = self; self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; self.tableView.showsHorizontalScrollIndicator = NO; self.tableView.showsVerticalScrollIndicator = NO; [self.tableView registerClass:[StudentInfoCell class] forCellReuseIdentifier:infoCellFlag]; [self.tableView registerClass:[ClassHeaderView class] forHeaderFooterViewReuseIdentifier:infoHeadFlag]; [self.view addSubview:self.tableView]; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { ClassModel *model = _classModels[section]; if (model.expend == YES) { return [model.students count]; } else { return 0; } } - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { if (self.sectionFirstLoad == NO) { return 0; } else { return [_classModels count]; } } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:infoCellFlag]; ClassModel *classModel = _classModels[indexPath.section]; StudentModel *studentModel = classModel.students[indexPath.row]; cell.data = studentModel; cell.indexPath = indexPath; [cell loadContent]; return cell; } - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { ClassHeaderView *titleView = [tableView dequeueReusableHeaderFooterViewWithIdentifier:infoHeadFlag]; titleView.delegate = self; titleView.data = _classModels[section]; titleView.section = section; [titleView loadContent]; if (section == 0) { self.tmpHeadView = titleView; } ClassModel *model = _classModels[section]; if (model.expend == YES) { [titleView extendStateAnimated:NO]; } else { [titleView normalStateAnimated:NO]; } return titleView; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 60; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 30; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { StudentInfoCell *cell = [tableView cellForRowAtIndexPath:indexPath]; [cell showSelectedAnimation]; [tableView deselectRowAtIndexPath:indexPath animated:YES]; } - (void)customHeaderFooterView:(CustomHeaderFooterView *)customHeaderFooterView event:(id)event { NSInteger section = customHeaderFooterView.section; ClassModel *model = _classModels[section]; ClassHeaderView *classHeaderView = (ClassHeaderView *)customHeaderFooterView; if (model.expend == YES) { // 缩回去 model.expend = NO; [classHeaderView normalStateAnimated:YES]; NSMutableArray *indexPaths = [NSMutableArray array]; for (int i = 0; i < model.students.count; i++) { [indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:section]]; } [self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; } else { // 显示出来 model.expend = YES; [classHeaderView extendStateAnimated:YES]; NSMutableArray *indexPaths = [NSMutableArray array]; for (int i = 0; i < model.students.count; i++) { [indexPaths addObject:[NSIndexPath indexPathForItem:i inSection:section]]; } [self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade]; } } - (void)firstLoadDataAnimation { [GCDQueue executeInMainQueue:^{ // Extend sections. self.sectionFirstLoad = YES; NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.classModels.count)]; [self.tableView insertSections:indexSet withRowAnimation:UITableViewRowAnimationFade]; [GCDQueue executeInMainQueue:^{ // Extend cells. [self customHeaderFooterView:self.tmpHeadView event:nil]; } afterDelaySecs:0.4f]; } afterDelaySecs:0.3f]; } @end
细节