iOS 開眼效果中的視差效果(UITableViewController)
阿新 • • 發佈:2019-01-31
前一段時間,自己看了一下開眼效果,覺得這個還是非常有意思啊。那麼,今天就來看看這個效果是如何實現的。
首先我們依然是先建立一個新的工程……
在ViewController.m中,新增一個私有屬性,並將其新增到self.view上:
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong)UITableView *tableView;
@end
@implementation ViewController
- (void )viewDidLoad {
[super viewDidLoad];
[self.view addSubview:self.tableView];
}
#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return 10;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
if (indexPath.row % 2 == 1) {
cell.backgroundColor = [UIColor blueColor];
}else {
cell.backgroundColor = [UIColor redColor];
}
return cell;
}
#pragma mark - UITableViewDelegate
#pragma mark - 懶載入
- (UITableView *)tableView {
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 20, self.view.bounds.size.width, self.view.bounds.size.height - 20) style:UITableViewStylePlain];
// 將tableview的資料來源和代理設定為當前控制器
_tableView.dataSource = self;
_tableView.delegate = self;
// 設定cell的高度
_tableView.rowHeight = 200;
_tableView.backgroundColor = [UIColor orangeColor];
// 設定tableview的原型cell
[_tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:@"cell"];
}
return _tableView;
}
@end
那麼,現在執行出來的效果是這樣的:
那麼,這個時候,我們需要自己建立一個新的型別,繼承於UITableViewCell,名字取為ShowTableViewCell,建立好後,將新的類匯入ViewController.m中。
現在,我們想在ShowTableViewCell.h中,增加一個屬性和兩個可以呼叫的方法。
@interface ShowTableViewCell : UITableViewCell
@property (nonatomic, strong)NSString *imageName;
- (void)cellOffSet; /**< 偏移單元格 */
- (void)cancelAnimation; /**< 取消動畫 */
@end
那麼,在ShowTableViewCell.m中,將圖片的位置進行懶載入,並且重寫imageName的set方法。
#import "ShowTableViewCell.h"
#define SCREEN_SIZE [UIScreen mainScreen].bounds.size
@interface ShowTableViewCell ()
@property (nonatomic, strong)UIImageView *backgroundImageView;
@end
@implementation ShowTableViewCell
- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
// 新增子檢視
// 1.配置cell的屬性
self.selectionStyle = UITableViewCellSelectionStyleNone;
self.clipsToBounds = YES;
// 2.試圖載入
[self.contentView addSubview:self.backgroundImageView];
// 3.自定義分割線
UIView *line = [[UIView alloc] initWithFrame:CGRectMake(0, 200 - 1, SCREEN_SIZE.width, 1)];
line.backgroundColor = [UIColor lightGrayColor];
[self.contentView addSubview:line];
return self;
}
#pragma mark - Handle offset
- (void)cancelAnimation {
[self.backgroundImageView.layer removeAllAnimations];
}
- (void)cellOffSet {
// 1、獲取cell在螢幕中的rect
CGRect centerToWindow = [self convertRect:self.bounds toView:self.window];
// 2、獲取cell中心點y軸座標
CGFloat centerY = CGRectGetMidY(centerToWindow);
// 3、獲取cell父檢視的中心點
CGPoint windowCenter = self.superview.center;
// 4、獲取距離差
CGFloat cellOffsetY = centerY - windowCenter.y;
// 5、距離差 / 2倍父檢視高度
CGFloat offsetDig = cellOffsetY / self.superview.frame.size.height * 2;
// 6、計算偏移 kScreenHeight * 0.5 為圖片檢視的高度
CGFloat offset = -offsetDig * (SCREEN_SIZE.height * 0.5 - 200) / 2;
CGAffineTransform transY = CGAffineTransformMakeTranslation(0, offset);
self.backgroundImageView.transform = transY;
}
#pragma mark - 重寫Set方法
- (void)setImageName:(NSString *)imageName {
if ([_imageName isEqualToString:imageName]) {
return;
}
_imageName = imageName;
self.backgroundImageView.image = [UIImage imageNamed:_imageName];
}
#pragma mark - 懶載入
- (UIImageView *)backgroundImageView {
if (!_backgroundImageView) {
_backgroundImageView = [[UIImageView alloc]initWithFrame:CGRectMake(0, - (SCREEN_SIZE.height * 0.5 - 200) / 2, SCREEN_SIZE.width, SCREEN_SIZE.height * 0.5)];
}
return _backgroundImageView;
}
@end
在ViewController.m中,將所有的UITableViewCell改為ShowTableViewCell,並且在整個demo中新增新增一張圖片。
- (ShowTableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ShowTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.imageName = @"青春3.jpg";
return cell;
}
上面的程式碼是從新將cell的屬性從新定義。
那麼,這個時候,我們只要將ShowTableViewCell的delegate從新書寫就OK了。
#pragma mark - UITableViewDelegate
// 將要顯示cell時呼叫
- (void)tableView:(UITableView *)tableView willDisplayCell:(ShowTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
// 1、cell 出現時的效果
// 防止載入時滑動卡頓
CATransform3D rotation;//3D旋轉
rotation = CATransform3DMakeTranslation(0 ,50 ,20);
// rotation = CATransform3DMakeRotation( M_PI_4 , 0.0, 0.7, 0.4);
// 逆時針旋轉
rotation = CATransform3DScale(rotation, 0.9, .9, 1);
rotation.m34 = 1.0/ -600;
cell.layer.shadowColor = [[UIColor blackColor]CGColor];
cell.layer.shadowOffset = CGSizeMake(10, 10);
cell.alpha = 0;
cell.layer.transform = rotation;
[UIView beginAnimations:@"rotation" context:NULL];
//旋轉時間
[UIView setAnimationDuration:0.6];
cell.layer.transform = CATransform3DIdentity;
cell.alpha = 1;
cell.layer.shadowOffset = CGSizeMake(0, 0);
[UIView commitAnimations];
// 2、滾動視差效果實現
[cell cellOffSet];
}
- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
// 獲取可以見到的 cell,讓圖片在cell座標改變的時候偏移
NSArray<ShowTableViewCell *> *array = [self.tableView visibleCells];
[array enumerateObjectsUsingBlock:^(ShowTableViewCell * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
[obj cellOffSet];
}];
}
// cell顯示完時呼叫
- (void)tableView:(UITableView *)tableView didEndDisplayingCell:(ShowTableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
[cell cancelAnimation];
}
那麼,全部就完成了,剩下的就command+r跑一下了。