UITableView 視差效果
之前在項目中用過一個視差效果,其實實現并不是很難,我們先看一下效果
視差效果.gif
大概說一下思路:
每個cell中有一個UIImageView,在tableview向上滑動的時候,cell中的imageview相對cell向下移動,形成一個視差效果。也就是說,除了屏幕最上端的cell中的imageview的y為0以外,下面的cell中的imageview的Y值均為負值。
接下來就依照已知量來計算每個imageView的y值,并且在tableview滾動的時候實時更改imageView的Y值。
已知量:
- tableView的高度(tableViewHeight)
- tableView的偏移量
- cell的高度
- imageView的高度
- cell的Y值
- cell相主屏幕的偏移量(cellOffset) -> cellY值 - tableView的偏移量
求imageView的偏移量(imageViewOffset)。如下圖所示。
圖解.png
思路:
當cell的偏移量變為0的時候,imageViewY的值也由負值變為0。
imageViewY的最大值為 imageViewHeight - cellHeight。
因此可得如下公式:
cellOffset/tableViewHeight = imageViewOffset/(imageViewHeight - cellHeight);
imageViewOffset = cellOffset/tableViewHeight * (imageViewHeight - cellHeight);
好了,啰嗦完了,上代碼:
新建一個工程,在工程中自定義一個cell,cell中放一個UIImageView控件,讓UIImageView控件的高度大于Cell的高度。我這里設置為300;cell的高度設為200;
并且增加兩個方法:
// 獲取圖片最大偏移量
- (CGFloat)imageOverflowHeight;
// 重新設置圖片偏移量
- (void)setImageOffset:(CGPoint)imageOffset;
自定義cell.m中的代碼如下:
-(instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
_mainImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, [[UIScreen mainScreen] bounds].size.width , 300)];
_mainImageView.contentMode = UIViewContentModeScaleAspectFill;
[self.contentView addSubview:_mainImageView];
_titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 80, [UIScreen mainScreen].bounds.size.width, 40)];
_titleLabel.backgroundColor = [UIColor colorWithRed:0.94 green:0.94 blue:0.94 alpha:0.50];
_titleLabel.text = @"這是圖片上的文字";
_titleLabel.textAlignment = 1;
[self.contentView addSubview:_titleLabel];
}
return self;
}
/**
* 返回圖片大于imageView的高度
*
* @return 圖片大于imageView的高度
*/
- (CGFloat)imageOverflowHeight
{
// 減200 是因為cell的高度設為200,所以直接寫固定值了
return _mainImageView.frame.size.height - 200;
}
/**
* 設置imageView偏移量
*
* @param imageOffset 偏移量
*/
- (void)setImageOffset:(CGPoint)imageOffset
{
CGRect frame = _mainImageView.frame;
frame.origin = imageOffset;
_mainImageView.frame = frame;
}
在VC中添加一個tableview控件,工程中拖入一些圖片備用。VC.m的代碼如下:
@interface ViewController ()<UITableViewDelegate, UITableViewDataSource>
@property (nonatomic, strong) NSMutableArray *sourceArr;
@property (nonatomic, strong) UITableView *mainTable;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
_sourceArr = [NSMutableArray array];
for (NSInteger i = 1; i <= 44; i++) {
NSString *imageName = [NSString stringWithFormat:@"img%ld.jpg", i];
[_sourceArr addObject:imageName];
}
_mainTable = [[UITableView alloc] initWithFrame:self.view.frame style:UITableViewStylePlain];
_mainTable.delegate = self;
_mainTable.dataSource = self;
_mainTable.separatorStyle = UITableViewCellSeparatorStyleNone;
[_mainTable registerClass:[LTParallaxCell class] forCellReuseIdentifier:@"cell"];
[self.view addSubview:_mainTable];
}
/**
* 設置imageView的偏移量
*
* @param cell
*/
- (void)updateImageViewCellOffset:(LTParallaxCell *)cell
{
// 獲取cell的偏移量
CGFloat cellOffset = cell.frame.origin.y - self.mainTable.contentOffset.y;
// 獲取imageView的最大偏移量
CGFloat imgMaxHeight = [cell imageOverflowHeight];
// 計算imageView新的偏移量
CGFloat offset = 0.0f - imgMaxHeight * cellOffset / self.mainTable.frame.size.height;
// 設置imageView新的偏移量
[cell setImageOffset:CGPointMake(0.0f, offset)];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_sourceArr count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
LTParallaxCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
cell.mainImageView.image = [UIImage imageNamed:[_sourceArr objectAtIndex:indexPath.row]];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.clipsToBounds = YES;
return cell;
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 200;
}
#pragma mark - UIScrollViewdelegate methods
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
for (LTParallaxCell *cell in self.mainTable.visibleCells) {
[self updateImageViewCellOffset:cell];
}
}
#pragma mark - UITableViewDelegate
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
[self updateImageViewCellOffset:(LTParallaxCell *)cell];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
至此,一個視差效果就完成了,如果有什么錯誤的地方歡迎大家指正。
來自:http://www.jianshu.com/p/00f069c91bea