UITableView 是iOS日常开发中经常使用到的控件。tableView的普通展示效果比较生硬,为了提升APP的活力,提升体验,我们可以对根据tableView的特点,操作Cell实现一些动画效果。
一、效果展示:
二、源代码:
TableViewAnimationKitHeaders.h
#ifndef TableViewAnimationKitHeaders_h
#define TableViewAnimationKitHeaders_h
#import "TableViewAnimationKit.h"
#import "UITableView+XSAnimationKit.h"
#endif /* TableViewAnimationKitHeaders_h */
TableViewAnimationKitConfig.h
#ifndef TableViewAnimationKitConfig_h
#define TableViewAnimationKitConfig_h
typedef NS_ENUM(NSInteger,XSTableViewAnimationType){
XSTableViewAnimationTypeMove = 0,
XSTableViewAnimationTypeMoveSpring = 0,
XSTableViewAnimationTypeAlpha,
XSTableViewAnimationTypeFall,
XSTableViewAnimationTypeShake,
XSTableViewAnimationTypeOverTurn,
XSTableViewAnimationTypeToTop,
XSTableViewAnimationTypeSpringList,
XSTableViewAnimationTypeShrinkToTop,
XSTableViewAnimationTypeLayDown,
XSTableViewAnimationTypeRote,
};
#endif /* TableViewAnimationKitConfig_h */
TableViewAnimationKit.h
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import "TableViewAnimationKitConfig.h"
@interface TableViewAnimationKit : NSObject<UICollisionBehaviorDelegate>
/**
class method to show the tableView animation
@param animationType : animation type
@param tableView : the tableView to show animation
*/
+ (void)showWithAnimationType:(XSTableViewAnimationType)animationType tableView:(UITableView *)tableView;
+ (void)moveAnimationWithTableView:(UITableView *)tableView;
+ (void)moveSpringAnimationWithTableView:(UITableView *)tableView;
+ (void)alphaAnimationWithTableView:(UITableView *)tableView;
+ (void)fallAnimationWithTableView:(UITableView *)tableView;
+ (void)shakeAnimationWithTableView:(UITableView *)tableView;
+ (void)overTurnAnimationWithTableView:(UITableView *)tableView;
+ (void)toTopAnimationWithTableView:(UITableView *)tableView;
+ (void)springListAnimationWithTableView:(UITableView *)tableView;
+ (void)shrinkToTopAnimationWithTableView:(UITableView *)tableView;
+ (void)layDownAnimationWithTableView:(UITableView *)tableView;
+ (void)roteAnimationWithTableView:(UITableView *)tableView;
@end
TableViewAnimationKit.m
#import "TableViewAnimationKit.h"
#import <objc/runtime.h>
#import <objc/message.h>
#define XS_SCREEN_WIDTH [[UIScreen mainScreen] bounds].size.width
#define XS_SCREEN_HEIGHT [[UIScreen mainScreen] bounds].size.height
@interface TableViewAnimationKit ()
@end
@implementation TableViewAnimationKit
+ (void)showWithAnimationType:(XSTableViewAnimationType)animationType tableView:(UITableView *)tableView{
unsigned int count = 0;
//Get Class Method
Method *methodlist = class_copyMethodList(object_getClass(self.class), &count);
int tag= 0;
for (int i = 0; i < count; i++) {
Method method = methodlist[i];
SEL selector = method_getName(method);
NSString *methodName = NSStringFromSelector(selector);
if ([methodName rangeOfString:@"AnimationWithTableView"].location != NSNotFound) {
if (tag == animationType) {
((void (*)(id,SEL,UITableView *))objc_msgSend)(self,selector,tableView);
break;
}
tag++;
}
}
free(methodlist);
}
+ (void)moveAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
for (int i = 0; i < cells.count; i++) {
CGFloat totalTime = 0.3;
UITableViewCell *cell = [tableView.visibleCells objectAtIndex:i];
cell.transform = CGAffineTransformMakeTranslation(-XS_SCREEN_WIDTH, 0);
[UIView animateWithDuration:0.25 delay:i*(totalTime/cells.count) options:0 animations:^{
cell.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
}
}
+ (void)moveSpringAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
for (int i = 0; i < cells.count; i++) {
CGFloat totalTime = 0.4;
UITableViewCell *cell = [tableView.visibleCells objectAtIndex:i];
cell.transform = CGAffineTransformMakeTranslation(-XS_SCREEN_WIDTH, 0);
[UIView animateWithDuration:0.4 delay:i*(totalTime/cells.count) usingSpringWithDamping:0.7 initialSpringVelocity:1/0.7 options:UIViewAnimationOptionCurveEaseIn animations:^{
cell.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
}
}
+ (void)alphaAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [tableView.visibleCells objectAtIndex:i];
cell.alpha = 0.0;
[UIView animateWithDuration:0.3 delay:i*0.05 options:0 animations:^{
cell.alpha = 1.0;
} completion:^(BOOL finished) {
}];
}
}
+ (void)fallAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
NSTimeInterval totalTime = 0.8;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [tableView.visibleCells objectAtIndex:i];
cell.transform = CGAffineTransformMakeTranslation(0, - XS_SCREEN_HEIGHT);
[UIView animateWithDuration:0.3 delay:(cells.count - i)*(totalTime/cells.count) options:0 animations:^{
cell.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
}
}
+ (void)shakeAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [cells objectAtIndex:i];
if (i%2 == 0) {
cell.transform = CGAffineTransformMakeTranslation(-XS_SCREEN_WIDTH,0);
}else {
cell.transform = CGAffineTransformMakeTranslation(XS_SCREEN_WIDTH,0);
}
[UIView animateWithDuration:0.4 delay:i*0.03 usingSpringWithDamping:0.75 initialSpringVelocity:1/0.75 options:0 animations:^{
cell.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
}
}
+ (void)overTurnAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [cells objectAtIndex:i];
cell.layer.opacity = 0.0;
cell.layer.transform = CATransform3DMakeRotation(M_PI, 1, 0, 0);
NSTimeInterval totalTime = 0.7;
[UIView animateWithDuration:0.3 delay:i*(totalTime/cells.count) options:0 animations:^{
cell.layer.opacity = 1.0;
cell.layer.transform = CATransform3DIdentity;
} completion:^(BOOL finished) {
}];
}
}
+ (void)toTopAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
NSTimeInterval totalTime = 0.8;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [tableView.visibleCells objectAtIndex:i];
cell.transform = CGAffineTransformMakeTranslation(0, XS_SCREEN_HEIGHT);
[UIView animateWithDuration:0.35 delay:i*(totalTime/cells.count) options:UIViewAnimationOptionCurveEaseOut animations:^{
cell.transform = CGAffineTransformIdentity;
} completion:^(BOOL finished) {
}];
}
}
+ (void)springListAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [cells objectAtIndex:i];
cell.layer.opacity = 0.7;
cell.layer.transform = CATransform3DMakeTranslation(0, -XS_SCREEN_HEIGHT, 20);
NSTimeInterval totalTime = 1.0;
[UIView animateWithDuration:0.4 delay:i*(totalTime/cells.count) usingSpringWithDamping:0.65 initialSpringVelocity:1/0.65 options:UIViewAnimationOptionCurveEaseIn animations:^{
cell.layer.opacity = 1.0;
cell.layer.transform = CATransform3DMakeTranslation(0, 0, 20);
} completion:^(BOOL finished) {
}];
}
}
+ (void)shrinkToTopAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [cells objectAtIndex:i];
CGRect rect = [cell convertRect:cell.bounds fromView:tableView];
cell.transform = CGAffineTransformMakeTranslation(0, -rect.origin.y);
[UIView animateWithDuration:0.5 animations:^{
cell.transform = CGAffineTransformIdentity;
}];
}
}
+ (void)layDownAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
NSMutableArray *rectArr = [[NSMutableArray alloc] init];
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [cells objectAtIndex:i];
CGRect rect = cell.frame;
[rectArr addObject:[NSValue valueWithCGRect:rect]];
rect.origin.y = i * 10;
cell.frame = rect;
cell.layer.transform = CATransform3DMakeTranslation(0, 0, i*5);
}
NSTimeInterval totalTime = 0.8;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [cells objectAtIndex:i];
CGRect rect = [[rectArr objectAtIndex:i] CGRectValue];
[UIView animateWithDuration:(totalTime/cells.count) * i animations:^{
cell.frame = rect;
} completion:^(BOOL finished) {
cell.layer.transform = CATransform3DIdentity;
}];
}
}
+ (void)roteAnimationWithTableView:(UITableView *)tableView {
NSArray *cells = tableView.visibleCells;
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.y"];
animation.fromValue = @(-M_PI);
animation.toValue = 0;
animation.duration = 0.3;
animation.removedOnCompletion = NO;
animation.repeatCount = 3;
animation.fillMode = kCAFillModeForwards;
animation.autoreverses = NO;
for (int i = 0; i < cells.count; i++) {
UITableViewCell *cell = [cells objectAtIndex:i];
cell.alpha = 0.0;
[UIView animateWithDuration:0.1 delay:i*0.25 options:0 animations:^{
cell.alpha = 1.0;
} completion:^(BOOL finished) {
[cell.layer addAnimation:animation forKey:@"rotationYkey"];
}];
}
}
@end
UITableView+XSAnimationKit.h
#import <UIKit/UIKit.h>
#import "TableViewAnimationKitConfig.h"
@interface UITableView (XSAnimationKit)
/**
show the tableView animation
@param animationType type of animation to show TableView
*/
- (void)xs_showTableViewAnimationWithType:(XSTableViewAnimationType )animationType;
@end
UITableView+XSAnimationKit.m
#import "UITableView+XSAnimationKit.h"
#import "TableViewAnimationKit.h"
@implementation UITableView (XSAnimationKit)
- (void)xs_showTableViewAnimationWithType:(XSTableViewAnimationType)animationType{
[TableViewAnimationKit showWithAnimationType:animationType tableView:self];
}
@end
三、使用
ViewController.h
#import <UIKit/UIKit.h>
@interface ViewController : UIViewController
@end
ViewController.m
#import "ViewController.h"
#import "BaseTableViewController.h"
@interface ViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) NSArray *titles;
@property (nonatomic, strong) UITableView *tableView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_titles = @[@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10"];
if (_titles) {
}else{
}
[self.view addSubview:self.tableView];
}
#pragma mark - Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return _titles.count;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
BaseTableViewController *vc = [[BaseTableViewController alloc] init];
vc.index = indexPath.row;
[self.navigationController pushViewController:vc animated:YES];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"identifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:identifier];
}
if (_titles.count > indexPath.row) {
cell.textLabel.text = _titles[indexPath.row];
}
return cell;
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
_tableView.dataSource = self;
_tableView.delegate = self;
}
return _tableView;
}
- (void)toTableViewVC {
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end
BaseTableViewController.h
#import <UIKit/UIKit.h>
@interface BaseTableViewController : UIViewController
@property (nonatomic, assign) NSInteger index;
@end
BaseTableViewController.m
#import "BaseTableViewController.h"
#import "TableViewAnimationKitHeaders.h"
@interface BaseTableViewController ()<UITableViewDelegate,UITableViewDataSource>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, assign) NSInteger cellNum;
@end
@implementation BaseTableViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.tableView];
[self performSelector:@selector(loadData) withObject:nil afterDelay:0.5];
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
btn.frame = CGRectMake(0, 0, 100, 50);
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
[btn setTitle:@"Show Again" forState:UIControlStateNormal];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:btn];
[btn addTarget:self action:@selector(loadData) forControlEvents:UIControlEventTouchUpInside];
}
- (void)loadData {
_cellNum = 15;
[self.tableView reloadData];
[self starAnimationWithTableView:self.tableView];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
}
#pragma mark - Delegate
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return self.cellNum;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 100;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *identifier = @"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
CGFloat width = [[UIScreen mainScreen] bounds].size.width - 40;
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(20, 10, width, 80)];
view.backgroundColor = [UIColor orangeColor];
view.layer.masksToBounds = YES;
view.layer.cornerRadius = 9.0;
[cell.contentView addSubview:view];
cell.contentView.backgroundColor = [UIColor clearColor];
cell.backgroundColor = [UIColor clearColor];
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
#pragma mark - Getter
-(UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStyleGrouped];
_tableView.delegate = self;
_tableView.dataSource = self;
[_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone];
}
return _tableView;
}
- (void)starAnimationWithTableView:(UITableView *)tableView {
[TableViewAnimationKit showWithAnimationType:self.index tableView:tableView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
@end