#import "TRCardListView.h"
#define TR_HEIGTH [UIScreen mainScreen].bounds.size.height
#define TR_WIDTH [UIScreen mainScreen].bounds.size.width
#ifndef __OPTIMIZE__
# define TRLog(...) NSLog(__VA_ARGS__)
#else
# define TRLog(...)
#endif
@interface TRCard : NSObject
@property (nonatomic, strong) UIView *view;
@property (nonatomic, assign) CGFloat positionY;
@end
@implementation TRCard
- (instancetype)initWithPositionY:(CGFloat)positionY{
if (self = [super init]) {
_positionY = positionY;
_view = nil;
}
return self;
}
@end
@interface TRCardListView()
@property (nonatomic, strong) UIView *contentView;
//用来存储card位置
@property (nonatomic, strong) NSMutableArray
@property (nonatomic, strong) NSMutableArray
@property (nonatomic, assign) NSInteger countOfCard;
@property (nonatomic) Class cardClass;
@end
@implementation TRCardListView
- (void)registerForReuseWithClass:(Class)cardClass{
_cardClass = cardClass;
[self updateLayout];
}
- (UIView *)dequeueReusableCardAtIndex:(NSInteger)index{
UIView *view = nil;
if (_unUsedCards.count > 0) {
view = _unUsedCards.firstObject;
}else{
UIView *card = [[_cardClass alloc] initWithFrame:CGRectMake(0, 0, TR_WIDTH, TR_HEIGTH)];
view = card;
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTapGesture:)];
[card addGestureRecognizer:tap];
// UISwipeGestureRecognizer *swipe = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeGesture:)];
// swipe.direction = UISwipeGestureRecognizerDirectionRight;
// [card addGestureRecognizer:swipe];
}
return view;
}
- (void)handleTapGesture:(UITapGestureRecognizer *)tap{
UIView *view = tap.view;
if (_trDelegate && [_trDelegate respondsToSelector:@selector(tr_cardListView:didSelectCardAtIndex:)]) {
for (int i = 0; i < self.countOfCard; i++) {
if (_cards[i].view) {
if (view == _cards[i].view) {
[_trDelegate tr_cardListView:self didSelectCardAtIndex:i];
break;
}
}
}
}
}
//- (void)handleSwipeGesture:(UISwipeGestureRecognizer *)swipe{
// NSLog(@"swipe");
// UIView *view = swipe.view;
//}
- (void)reloadData{
[self initCards];
[self updateLayout];
}
- (void)awakeFromNib{
[super awakeFromNib];
[self setupContentView];
[self setupDefaultValue];
self.contentView.frame = self.bounds;
}
- (instancetype)init{
if (self = [super init]) {
[self setupDefaultValue];
[self setupContentView];
}
return self;
}
- (void)setFrame:(CGRect)frame{
[super setFrame:frame];
self.contentView.frame = self.bounds;
}
- (instancetype)initWithFrame:(CGRect)frame{
if (self = [super initWithFrame:frame]) {
[self setupContentView];
[self setupDefaultValue];
}
return self;
}
- (void)setupContentView{
_contentView = [[UIView alloc] init];
_contentView.backgroundColor = [UIColor clearColor];
[self addSubview:_contentView];
}
- (void)setupDefaultValue{
_top = 64.0;
_distance = 64.0;
}
- (void)initCards{
_cards = [NSMutableArray array];
_unUsedCards = [NSMutableArray array];
NSInteger count = self.countOfCard;
for (NSInteger i = 0; i < count; i++) {
TRCard *card = [[TRCard alloc] initWithPositionY:0];
[_cards insertObject:card atIndex:0];
}
}
- (void)setTrDelegate:(id
_trDelegate = trDelegate;
if (self.countOfCard) {
[self initCards];
[self updateLayout];
}
}
- (void)setTrDataSource:(id
_trDataSource = trDataSource;
if (self.countOfCard) {
[self initCards];
[self updateLayout];
}
}
- (NSInteger)countOfCard{
if (_trDataSource && [_trDataSource respondsToSelector:@selector(tr_numberOfCardsInCardListView:)]) {
return [_trDataSource tr_numberOfCardsInCardListView:self];
}
return 0;
}
- (void)setTop:(CGFloat)top{
_top = top;
[self updateLayout];
}
- (void)setDistance:(CGFloat)distance{
_distance = distance;
[self updateLayout];
}
- (void)setContentOffset:(CGPoint)contentOffset{
[self updateLayoutOfCardWithContentOffset:contentOffset];
[super setContentOffset:contentOffset];
}
- (void)updateLayout{
self.contentSize = CGSizeMake(TR_WIDTH, TR_HEIGTH + self.distance * self.countOfCard - 1.5);
self.contentOffset = CGPointMake(0, 0);
}
- (void)updateLayoutOfCardWithContentOffset:(CGPoint)contentOffset{
self.contentView.frame = CGRectMake(0, contentOffset.y, TR_WIDTH, TR_HEIGTH);
[_cards enumerateObjectsUsingBlock:^(TRCard * card, NSUInteger idx, BOOL *stop) {
NSInteger value = self.distance;
/*************设置位置***************/
NSInteger begin_y = value * (self.countOfCard - idx - 1);
CGFloat distance_y = self.contentSize.height - contentOffset.y - TR_HEIGTH - begin_y;
CGFloat positionY = self.top + pow(distance_y, 2) / pow(2, 6);
if (distance_y >= -50) {
CGFloat alpha = distance_y >= 0?1:(distance_y + 50)/ 50;
card.view.alpha = alpha;
}else{
card.view.alpha = 0;
}
card.positionY = positionY;
if (positionY <= TR_HEIGTH) {
if (card.view == nil) {
[self setViewInCard:card atIndex:idx];
[self addCardWithCard:card atIndex:idx];;
}
[self updateOriginWithView:card.view newOriginY:positionY];
/*************设置大小***************/
CGFloat scale = 0.70;
scale = (positionY * 0.75 + 70) / 1000 + scale >= 0.95?0.95:(positionY * 0.75 + 50) / 1000 + scale;
card.view.layer.transform = CATransform3DMakeScale(scale, scale, 1);
}else{
if (card.view != nil) {
[_unUsedCards addObject:card.view];
[card.view removeFromSuperview];
card.view = nil;
}
}
}];
}
- (void)setViewInCard:(TRCard *)card atIndex:(NSInteger)index{
if (self.trDataSource && [self.trDataSource respondsToSelector:@selector(tr_cardListView:cardAtIndex:)]) {
UIView * view = [self.trDataSource tr_cardListView:self cardAtIndex:index];
card.view = view;
if ([_unUsedCards containsObject:view]) {
[_unUsedCards removeObject:view];
}
}else{
TRLog(@"未实现 Method: \"tr_carListView:cardAtIndex:\"");
}
}
- (void)addCardWithCard:(TRCard *)card atIndex:(NSInteger)index{
if (index == 0) {
[self.contentView insertSubview:card.view atIndex:0];
}else if (index == self.countOfCard - 1){
[self.contentView addSubview:card.view];
}else if (self.cards[index + 1].view){
[self.contentView insertSubview:card.view atIndex:0];
}else if (self.cards[index - 1].view){
[self.contentView addSubview:card.view];
}
}
- (void)updateOriginWithView:(UIView *)view newOriginY:(CGFloat)originY{
CGSize size = view.frame.size;
view.frame = CGRectMake(view.frame.origin.x, originY, size.width, size.height);
}
@end//
// TRCardListView.m
// 卡片堆叠效果实现
//
// Created by cry on 2017/6/8.
// Copyright © 2017年 egova. All rights reserved.
//
#import "TRCardListView.h"
#define TR_HEIGTH [UIScreen mainScreen].bounds.size.height
#define TR_WIDTH [UIScreen mainScreen].bounds.size.width
#ifndef __OPTIMIZE__
# define TRLog(...) NSLog(__VA_ARGS__)
#else
# define TRLog(...)
#endif
@interface TRCard : NSObject
@property (nonatomic, strong) UIView *view;
@property (nonatomic, assign) CGFloat positionY;
@end
@implementation TRCard
- (instancetype)initWithPositionY:(CGFloat)positionY{
if (self = [super init]) {
_positionY = positionY;
_view = nil;
}
return self;
}
@end
@interface TRCardListView()
@property (nonatomic, strong) UIView *contentView;
//用来存储card位置
@property (nonatomic, strong) NSMutableArray
@property (nonatomic, strong) NSMutableArray
@property (nonatomic, assign) NSInteger countOfCard;
@property (nonatomic