您的位置:首页 > 移动开发 > Objective-C

tableView视差滚动

2016-01-29 00:00 393 查看
摘要: 当tableView滚动时,cell中的图片会上下微移(相对于cell本身),在视觉上给人一种透过窗户看屋内事物的视觉差错感。具体实现详见正文。

code:

//
//  SHParallaxCell.m
//  tableView视差滚动
//
//  Created by 邵瑞波 on 16/1/28.
//  Copyright © 2016年 邵瑞波. All rights reserved.
//

#import "SHParallaxCell.h"
#import "Masonry.h"

/*
简化版中,scrollView 不是必须的。
*/

@interface SHParallaxCell()
@property (nonatomic, strong) UIScrollView *scrollView;  // 视差容器视图
@property (nonatomic, strong) UIImageView *imgView;      // 视图`图片展示`视图
@property (nonatomic, weak) UITableView *tableView;      // 父视图 tableView
@end

@implementation SHParallaxCell

- (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier {
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];

if (self) {
[self setupUI];
}

return self;
}

- (void)awakeFromNib {
// Initialization code

[self setupUI];
}

- (void)setSelected:(BOOL)selected animated:(BOOL)animated {
[super setSelected:selected animated:animated];

// Configure the view for the selected state
}

- (void)layoutSubviews {
[super layoutSubviews];

// 约束
}

// 记录 父视图 tableView
- (void)willMoveToSuperview:(UIView *)newSuperview {

//NSLog(@"newSuperview=[%@]", newSuperview);

UIView *view = newSuperview;

// 查找 tableView
while (view) {
if ([view isKindOfClass:[UITableView class]]) {
self.tableView = (UITableView *)view;
// 添加 kvo 监听
[self.tableView addObserver:self
forKeyPath:@"contentOffset"
options:NSKeyValueObservingOptionNew
context:nil];
break;
} else {
view = view.superview;
}
}
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
//    NSLog(@"object=[%@]", object);
//    NSLog(@"cell.frame=[%@], change[@\"new\"]=[%@]", NSStringFromCGRect(self.frame) , change[@"new"]);

CGPoint offSet = [change[@"new"] CGPointValue];
CGFloat height = self.scrollView.bounds.size.height;

offSet.y += height;
CGFloat detal = offSet.y - self.frame.origin.y;
CGFloat a = detal / height * 20.0;

// 如果性能不行,这里可以考虑 `主线程异步`
[self.imgView updateConstraints:^(MASConstraintMaker *make) {
make.centerY.equalTo(self.scrollView.centerY).offset(a);
}];

//    dispatch_async(dispatch_get_main_queue(), ^{
//        // 如果性能不行,这里可以考虑 `主线程异步`
//        [self.imgView updateConstraints:^(MASConstraintMaker *make) {
//            make.centerY.equalTo(self.scrollView.centerY).offset(a);
//        }];
//    });
}

// 设置 image
- (void)setImage:(UIImage *)image {
if (!(self.imgView.image == image)) {
self.imgView.image = image;
}
}

#pragma mark - 初始化设置

- (void)setupUI {
self.selectionStyle = UITableViewCellSelectionStyleNone;
[self.contentView addSubview:self.scrollView];

// 约束
[self.contentView makeConstraints:^(MASConstraintMaker *make) {
make.width.equalTo(self);
make.height.equalTo(200);
}];

[self.scrollView makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.contentView).offset(8);
make.left.equalTo(self.contentView).offset(8);
make.right.equalTo(self.contentView).offset(-8);
make.bottom.equalTo(self.contentView).offset(-8);
}];

[self.imgView makeConstraints:^(MASConstraintMaker *make) {
//        make.center.equalTo(self.scrollView);
make.centerX.equalTo(self.scrollView.centerX);
make.centerY.equalTo(self.scrollView.centerY);
make.width.equalTo(self.scrollView);
make.height.equalTo(240);

self.scrollView.contentSize = CGSizeMake(0, 240);
}];

/*
内容视图大小的size的高度为 200、image的高度为240、
计算:
上下方的滚动范围均为 20
*/
}

#pragma mark - 懒加载控件

- (UIScrollView *)scrollView {
if (!_scrollView) {
_scrollView = [[UIScrollView alloc] init];

_scrollView.userInteractionEnabled = NO;
_scrollView.showsVerticalScrollIndicator = NO;
_scrollView.showsHorizontalScrollIndicator = NO;
_scrollView.bounces = NO;
_scrollView.backgroundColor = [UIColor whiteColor];
_scrollView.layer.cornerRadius = 8;
_scrollView.clipsToBounds = YES;

[_scrollView addSubview:self.imgView];
}
return _scrollView;
}

- (UIImageView *)imgView {
if (!_imgView) {
_imgView = [[UIImageView alloc] init];
_imgView.contentMode = UIViewContentModeScaleAspectFill;  // 填充模式
//        _imgView.backgroundColor = [UIColor cyanColor];
}
return _imgView;
}

#pragma mark - 销毁 kvo 监听,否则会崩溃

- (void)dealloc {
[self.tableView removeObserver:self forKeyPath:@"contentOffset"];
}

@end
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息