之前在项目中用过一个视差效果,其实实现并不是很难,我们先看一下效果 </br>
视差效果.gif大概说一下思路:</br>
每个cell中有一个UIImageView,在tableview向上滑动的时候,cell中的imageview相对cell向下移动,形成一个视差效果。也就是说,除了屏幕最上端的cell中的imageview的y为0以外,下面的cell中的imageview的Y值均为负值。
接下来就依照已知量来计算每个imageView的y值,并且在tableview滚动的时候实时更改imageView的Y值。
已知量:</br>
- tableView的高度(tableViewHeight)</br>
- tableView的偏移量</br>
- cell的高度</br>
- imageView的高度</br>
- cell的Y值
- cell相主屏幕的偏移量(cellOffset) -> cellY值 - tableView的偏移量</br>
求imageView的偏移量(imageViewOffset)。如下图所示。
图解.png思路:
当cell的偏移量变为0的时候,imageViewY的值也由负值变为0。</br>
imageViewY的最大值为 imageViewHeight - cellHeight。</br>
因此可得如下公式:</br>
cellOffset/tableViewHeight = imageViewOffset/(imageViewHeight - cellHeight);</br>
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
至此,一个视差效果就完成了,如果有什么错误的地方欢迎大家指正。</br>
本人个人博客地址:http://www.lrymlt.cn/blog/
网友评论