├── .DS_Store ├── CCFoldCellDemo ├── CCFoldCell │ ├── CCFoldCell.h │ ├── CCFoldCell.m │ ├── CCRotatedView.h │ ├── CCRotatedView.m │ ├── UIView+Snapshot.h │ └── UIView+Snapshot.m ├── CCFoldCellDemo.xcodeproj │ ├── project.pbxproj │ ├── project.xcworkspace │ │ ├── contents.xcworkspacedata │ │ └── xcuserdata │ │ │ └── ehome.xcuserdatad │ │ │ └── UserInterfaceState.xcuserstate │ └── xcuserdata │ │ └── ehome.xcuserdatad │ │ └── xcschemes │ │ ├── CCFoldCellDemo.xcscheme │ │ └── xcschememanagement.plist ├── CCFoldCellDemo │ ├── AppDelegate.h │ ├── AppDelegate.m │ ├── Assets.xcassets │ │ ├── AppIcon.appiconset │ │ │ └── Contents.json │ │ ├── Contents.json │ │ ├── arrow.imageset │ │ │ ├── Contents.json │ │ │ └── arrow.pdf │ │ ├── background.imageset │ │ │ ├── Contents.json │ │ │ └── background.png │ │ ├── burger.imageset │ │ │ ├── Contents.json │ │ │ └── burger.pdf │ │ ├── dots.imageset │ │ │ ├── Contents.json │ │ │ └── dots.pdf │ │ ├── image.imageset │ │ │ ├── Contents.json │ │ │ └── image.png │ │ ├── photo.imageset │ │ │ ├── Contents.json │ │ │ └── photo.pdf │ │ └── stars.imageset │ │ │ ├── Contents.json │ │ │ └── stars.pdf │ ├── Base.lproj │ │ ├── LaunchScreen.storyboard │ │ └── Main.storyboard │ ├── DemoCell.h │ ├── DemoCell.m │ ├── DemoCell.xib │ ├── Info.plist │ ├── ViewController.h │ ├── ViewController.m │ └── main.m ├── CCFoldCellDemoTests │ ├── CCFoldCellDemoTests.m │ └── Info.plist └── CCFoldCellDemoUITests │ ├── CCFoldCellDemoUITests.m │ └── Info.plist ├── README.md └── image ├── 2view.png ├── CCFoldCell.gif ├── CheckCell.png ├── SetCellProperty.png ├── avatar.png └── bindOutlets.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/.DS_Store -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCell/CCFoldCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // CCFoldingCell.h 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CCRotatedView.h" 11 | 12 | typedef NS_ENUM(NSInteger,AnimationType) { 13 | AnimationTypeOpen, 14 | AnimationTypeClose 15 | }; 16 | 17 | @interface CCFoldCell : UITableViewCell 18 | 19 | @property (nonatomic, weak) IBOutlet UIView *containerView; 20 | @property (nonatomic, weak) IBOutlet NSLayoutConstraint *containerViewTop; 21 | 22 | @property (nonatomic, weak) IBOutlet CCRotatedView *foregroundView; 23 | @property (nonatomic, weak) IBOutlet NSLayoutConstraint *foregroundViewTop; 24 | 25 | @property (nonatomic, strong) UIView *animationView; 26 | @property (nonatomic, assign) IBInspectable NSInteger itemCount; 27 | @property (nonatomic, strong) IBInspectable UIColor *backViewColor; 28 | 29 | @property (nonatomic, strong) NSMutableArray *animationItemViews; 30 | 31 | - (BOOL)isAnimating; 32 | 33 | - (NSTimeInterval)animationDurationWithItemIndex:(NSInteger)itemIndex animationType:(AnimationType)type; 34 | 35 | - (void)selectedAnimationByIsSelected:(BOOL)isSelected animated:(BOOL)animated completion:(void(^)())completion; 36 | 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCell/CCFoldCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // CCFoldingCell.m 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import "CCFoldCell.h" 10 | #import "UIView+Snapshot.h" 11 | 12 | IB_DESIGNABLE 13 | @implementation CCFoldCell 14 | 15 | - (void)awakeFromNib { 16 | [super awakeFromNib]; 17 | // Initialization code 18 | [self commonInit]; 19 | } 20 | 21 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 22 | [super setSelected:selected animated:animated]; 23 | 24 | // Configure the view for the selected state 25 | } 26 | 27 | - (void)commonInit 28 | { 29 | [self configureDefaultState]; 30 | 31 | self.selectionStyle = UITableViewCellSelectionStyleNone; 32 | 33 | self.containerView.layer.cornerRadius = self.foregroundView.layer.cornerRadius; 34 | self.containerView.layer.masksToBounds = YES; 35 | } 36 | 37 | - (void)configureDefaultState 38 | { 39 | NSLayoutConstraint *foregroundViewTop = self.foregroundViewTop; 40 | NSLayoutConstraint *containerViewTop = self.containerViewTop; 41 | 42 | NSAssert(foregroundViewTop != nil, @"set foregroundViewTop constraint outlets"); 43 | NSAssert(containerViewTop != nil, @"set containerViewTop constraint outlaets"); 44 | 45 | containerViewTop.constant = foregroundViewTop.constant; 46 | self.containerView.alpha = 0; 47 | 48 | NSMutableArray *filterArray = [NSMutableArray array]; 49 | for (NSLayoutConstraint *constraint in self.foregroundView.constraints) { 50 | if (constraint.firstAttribute == NSLayoutAttributeHeight && constraint.secondItem == nil) { 51 | [filterArray addObject:constraint]; 52 | } 53 | } 54 | 55 | CGFloat height = filterArray.firstObject.constant; 56 | 57 | if (height) { 58 | self.foregroundView.layer.anchorPoint = CGPointMake(0.5, 1); 59 | self.foregroundViewTop.constant += height / 2; 60 | } 61 | self.foregroundView.layer.transform = [self.foregroundView rotateTransform3d]; 62 | 63 | [self createAnimationView]; 64 | [self.contentView bringSubviewToFront:self.foregroundView]; 65 | } 66 | 67 | - (void)createAnimationView 68 | { 69 | self.animationView = [[UIView alloc] initWithFrame:self.containerView.frame]; 70 | 71 | self.animationView.layer.cornerRadius = self.foregroundView.layer.cornerRadius; 72 | self.animationView.backgroundColor = [UIColor clearColor]; 73 | self.animationView.translatesAutoresizingMaskIntoConstraints = NO; 74 | self.animationView.alpha = 0; 75 | 76 | UIView *animationView = self.animationView; 77 | 78 | if (!animationView) return; 79 | 80 | [self.contentView addSubview:animationView]; 81 | 82 | NSMutableArray *newConstraints = [NSMutableArray array]; 83 | 84 | for (NSLayoutConstraint *constraint in self.contentView.constraints) { 85 | UIView *item = constraint.firstItem; 86 | UIView *secondItem = constraint.secondItem; 87 | if (item == self.containerView) { 88 | NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:animationView 89 | attribute:constraint.firstAttribute 90 | relatedBy:constraint.relation 91 | toItem:constraint.secondItem 92 | attribute:constraint.secondAttribute 93 | multiplier:constraint.multiplier 94 | constant:constraint.constant]; 95 | 96 | [newConstraints addObject:newConstraint]; 97 | }else if (secondItem == self.containerView) 98 | { 99 | NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:constraint.firstItem 100 | attribute:constraint.firstAttribute 101 | relatedBy:constraint.relation 102 | toItem:animationView 103 | attribute:constraint.secondAttribute 104 | multiplier:constraint.multiplier 105 | constant:constraint.constant]; 106 | [newConstraints addObject:newConstraint]; 107 | } 108 | } 109 | 110 | [self.contentView addConstraints:newConstraints]; 111 | 112 | for (NSLayoutConstraint *constraint in self.containerView.constraints) { 113 | if (constraint.firstAttribute == NSLayoutAttributeHeight) { 114 | NSLayoutConstraint *newConstraint = [NSLayoutConstraint constraintWithItem:animationView 115 | attribute:constraint.firstAttribute 116 | relatedBy:constraint.relation 117 | toItem:nil 118 | attribute:constraint.secondAttribute 119 | multiplier:constraint.multiplier 120 | constant:constraint.constant]; 121 | [animationView addConstraint:newConstraint]; 122 | } 123 | } 124 | } 125 | 126 | - (void)addImageItemsToAnimationView 127 | { 128 | self.containerView.alpha = 1; 129 | CGSize containerSize = self.containerView.bounds.size; 130 | CGSize foregroundSize = self.foregroundView.bounds.size; 131 | 132 | //添加第一张图片 133 | UIImage *image = [self.containerView takeSnapshotWithFrame:CGRectMake(0, 0, containerSize.width, foregroundSize.height)]; 134 | UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 135 | imageView.frame = CGRectMake(0, 0, containerSize.width, foregroundSize.height); 136 | 137 | imageView.tag = 0; 138 | imageView.layer.cornerRadius = self.foregroundView.layer.cornerRadius; 139 | 140 | if(self.animationView) 141 | [self.animationView addSubview:imageView]; 142 | 143 | //添加第二张图片 144 | image = [self.containerView takeSnapshotWithFrame:CGRectMake(0, foregroundSize.height, containerSize.width, foregroundSize.height)]; 145 | 146 | imageView = [[UIImageView alloc] initWithImage:image]; 147 | imageView.backgroundColor = [UIColor clearColor]; 148 | imageView.frame = CGRectMake(0, 0, containerSize.width, foregroundSize.height); 149 | CCRotatedView *rotatedView = [[CCRotatedView alloc] initWithFrame:CGRectMake(0, foregroundSize.height, containerSize.width, foregroundSize.height)]; 150 | rotatedView.tag = 1; 151 | rotatedView.alpha = 0; 152 | rotatedView.layer.anchorPoint = CGPointMake(0.5, 0); 153 | rotatedView.layer.transform = [rotatedView rotateTransform3d]; 154 | 155 | [rotatedView addSubview:imageView]; 156 | 157 | if (self.animationView) 158 | [self.animationView addSubview:rotatedView]; 159 | 160 | rotatedView.frame = CGRectMake(imageView.frame.origin.x, foregroundSize.height, containerSize.width, foregroundSize.height); 161 | 162 | CGFloat itemHeight = (containerSize.height - 2 * foregroundSize.height) / (self.itemCount - 2.f); 163 | 164 | if (self.itemCount == 2) { 165 | NSAssert(containerSize.height - 2 * foregroundSize.height != 0, @"contanerView.height too high"); 166 | }else 167 | { 168 | NSAssert(containerSize.height - 2 * foregroundSize.height >= itemHeight, @"contanerView.height too high"); 169 | } 170 | 171 | CGFloat yPositon = 2 * foregroundSize.height; 172 | NSInteger tag = 2; 173 | 174 | for (NSInteger i = 2; i < self.itemCount; i ++) { 175 | image = [self.containerView takeSnapshotWithFrame:CGRectMake(0, yPositon, containerSize.width, itemHeight)]; 176 | imageView = [[UIImageView alloc] initWithImage:image]; 177 | imageView.backgroundColor = [UIColor clearColor]; 178 | imageView.frame = CGRectMake(0, 0, containerSize.width, itemHeight); 179 | CCRotatedView *otherRotatedView = [[CCRotatedView alloc] initWithFrame:CGRectMake(0, yPositon, containerSize.width, itemHeight)]; 180 | otherRotatedView.alpha = 0; 181 | [otherRotatedView addSubview:imageView]; 182 | otherRotatedView.layer.anchorPoint = CGPointMake(0.5, 0); 183 | otherRotatedView.layer.transform = [otherRotatedView rotateTransform3d]; 184 | otherRotatedView.frame = CGRectMake(0, yPositon, otherRotatedView.bounds.size.width, itemHeight); 185 | otherRotatedView.tag = tag; 186 | 187 | if (self.animationView) 188 | [self.animationView addSubview:otherRotatedView]; 189 | 190 | 191 | yPositon += itemHeight; 192 | tag += 1; 193 | } 194 | 195 | self.containerView.alpha = 0; 196 | 197 | UIView *animationView = self.animationView; 198 | if (animationView) { 199 | CCRotatedView *previusView; 200 | NSArray *sortArray = [animationView.subviews sortedArrayUsingComparator:^NSComparisonResult(UIView * _Nonnull obj1, UIView * _Nonnull obj2) { 201 | if (obj1.tag < obj2.tag) { 202 | return NSOrderedAscending; 203 | }else if (obj1.tag == obj2.tag) 204 | { 205 | return NSOrderedSame; 206 | }else 207 | { 208 | return NSOrderedDescending; 209 | } 210 | }]; 211 | 212 | 213 | for (CCRotatedView *container in sortArray) { 214 | if (![container isKindOfClass:[CCRotatedView class]]) { 215 | continue; 216 | } 217 | NSLog(@"%ld",container.tag); 218 | if (container.tag > 0 && container.tag < animationView.subviews.count) { 219 | if (previusView) { 220 | [previusView addBackViewWithHeight:container.bounds.size.height color:self.backViewColor]; 221 | } 222 | previusView = container; 223 | 224 | } 225 | } 226 | 227 | } 228 | 229 | self.animationItemViews = [self createAnimationItemView]; 230 | } 231 | 232 | - (void)removeImageItemsFromAnimationView 233 | { 234 | UIView *animationView = self.animationView; 235 | 236 | if (animationView) 237 | [animationView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 238 | 239 | } 240 | 241 | - (NSMutableArray *)createAnimationItemView 242 | { 243 | UIView *animationView = self.animationView; 244 | 245 | NSAssert(animationView != nil, @"animationView is nil"); 246 | 247 | NSMutableArray *items = [NSMutableArray array]; 248 | [items addObject:self.foregroundView]; 249 | 250 | NSMutableArray *rotatedViews = [NSMutableArray array]; 251 | 252 | NSMutableArray *fileterArray = [NSMutableArray array]; 253 | for (UIView *view in animationView.subviews) { 254 | if ([view isKindOfClass:[CCRotatedView class]]) { 255 | CCRotatedView *rotatedView = (CCRotatedView *)view; 256 | [fileterArray addObject:rotatedView]; 257 | } 258 | } 259 | 260 | NSArray *sortArray = [fileterArray sortedArrayUsingComparator:^NSComparisonResult(UIView * _Nonnull obj1, UIView * _Nonnull obj2) { 261 | if (obj1.tag < obj2.tag) { 262 | return NSOrderedAscending; 263 | }else if (obj1.tag == obj2.tag) 264 | { 265 | return NSOrderedSame; 266 | }else 267 | { 268 | return NSOrderedDescending; 269 | } 270 | }]; 271 | 272 | 273 | 274 | for (CCRotatedView *itemView in sortArray) { 275 | [rotatedViews addObject:itemView]; 276 | CCRotatedView *backView = itemView.backView; 277 | if (backView) { 278 | [rotatedViews addObject:backView]; 279 | } 280 | } 281 | 282 | [items addObjectsFromArray:rotatedViews]; 283 | return items; 284 | } 285 | 286 | - (void)configureAnimationItemsWithAnimationType:(AnimationType)animationType 287 | { 288 | NSArray *animationViewSubViews = self.animationView.subviews; 289 | 290 | NSAssert(animationViewSubViews != nil, @"animationViewSubView is nil"); 291 | 292 | NSMutableArray *animationSubRotatedViews = [NSMutableArray array]; 293 | 294 | for (UIView *view in animationViewSubViews) { 295 | if ([view isKindOfClass:[CCRotatedView class]]) { 296 | [animationSubRotatedViews addObject:view]; 297 | } 298 | } 299 | 300 | if (animationType == AnimationTypeOpen) { 301 | for (UIView *view in animationSubRotatedViews) { 302 | view.alpha = 0; 303 | } 304 | }else 305 | { 306 | for (CCRotatedView *view in animationSubRotatedViews) { 307 | view.alpha = 1; 308 | view.backView.alpha = 0; 309 | } 310 | } 311 | } 312 | 313 | 314 | - (void)selectedAnimationByIsSelected:(BOOL)isSelected animated:(BOOL)animated completion:(void(^)())completion 315 | { 316 | if (isSelected) { 317 | if (animated) { 318 | self.containerView.alpha = 0; 319 | [self openAnimationWithCompletion:completion]; 320 | }else 321 | { 322 | self.foregroundView.alpha = 0; 323 | self.containerView.alpha = 1; 324 | } 325 | }else 326 | { 327 | if (animated) { 328 | [self closeAnimationWithCompletion:completion]; 329 | }else 330 | { 331 | self.foregroundView.alpha = 1; 332 | self.containerView.alpha = 0; 333 | } 334 | } 335 | } 336 | 337 | - (BOOL)isAnimating 338 | { 339 | return self.animationView.alpha == 1 ? YES : NO; 340 | } 341 | 342 | - (NSTimeInterval)animationDurationWithItemIndex:(NSInteger)itemIndex animationType:(AnimationType)type 343 | { 344 | NSAssert(NO, @"added this method to cell"); 345 | return 0; 346 | } 347 | 348 | - (NSMutableArray *)durationSequenceWithType:(AnimationType)type 349 | { 350 | NSMutableArray *durations = [NSMutableArray array]; 351 | 352 | for (int index = 0; index < self.itemCount - 1; index ++) { 353 | NSTimeInterval duration = [self animationDurationWithItemIndex:index animationType:type]; 354 | [durations addObject:@(duration / 2)]; 355 | [durations addObject:@(duration / 2)]; 356 | } 357 | return durations; 358 | } 359 | 360 | - (void)openAnimationWithCompletion:(void(^)())completion 361 | { 362 | [self removeImageItemsFromAnimationView]; 363 | [self addImageItemsToAnimationView]; 364 | 365 | UIView *animationView = self.animationView; 366 | if (!animationView) return; 367 | 368 | animationView.alpha = 1; 369 | self.containerView.alpha = 0; 370 | 371 | NSMutableArray *durations = [self durationSequenceWithType:AnimationTypeOpen]; 372 | 373 | NSTimeInterval delay = 0; 374 | NSString *timing = kCAMediaTimingFunctionEaseIn; 375 | CGFloat from = 0.f; 376 | CGFloat to = -M_PI / 2; 377 | BOOL hidden = YES; 378 | 379 | NSMutableArray *animationItemViews = self.animationItemViews; 380 | if (!animationItemViews) { return; } 381 | 382 | for (int index = 0; index < animationItemViews.count; index ++) { 383 | CCRotatedView *animatedView = animationItemViews[index]; 384 | 385 | [animatedView foldingAnimationWithTimingFunctionString:timing from:from to:to duration:durations[index].doubleValue delay:delay hidden:hidden]; 386 | 387 | from = from == 0.f ? M_PI / 2 : 0.f; 388 | to = to == 0.f ? - M_PI / 2 : 0.f; 389 | timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn; 390 | hidden = !hidden; 391 | delay += durations[index].doubleValue; 392 | } 393 | 394 | NSMutableArray *tagZeroArray = [NSMutableArray array]; 395 | for (UIView *view in animationView.subviews) { 396 | if (view.tag == 0) { 397 | [tagZeroArray addObject:view]; 398 | } 399 | } 400 | 401 | UIView *firstItemView = tagZeroArray.firstObject; 402 | 403 | firstItemView.layer.masksToBounds = YES; 404 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(durations[0].doubleValue * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 405 | firstItemView.layer.cornerRadius = 0; 406 | }); 407 | 408 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 409 | self.animationView.alpha = 0; 410 | self.containerView.alpha = 1; 411 | 412 | if (completion) completion(); 413 | }); 414 | } 415 | 416 | - (void)closeAnimationWithCompletion:(void(^)())completion 417 | { 418 | [self removeImageItemsFromAnimationView]; 419 | [self addImageItemsToAnimationView]; 420 | 421 | NSMutableArray *animationItemViews = self.animationItemViews; 422 | NSAssert(animationItemViews != nil, @"animationItemViews is nil"); 423 | 424 | self.animationView.alpha = 1; 425 | self.containerView.alpha = 0; 426 | 427 | NSArray *durations = [[[self durationSequenceWithType:AnimationTypeClose] reverseObjectEnumerator] allObjects]; 428 | 429 | NSTimeInterval delay = 0; 430 | NSString *timing = kCAMediaTimingFunctionEaseIn; 431 | CGFloat from = 0.f; 432 | CGFloat to = M_PI / 2; 433 | BOOL hidden = YES; 434 | 435 | [self configureAnimationItemsWithAnimationType:AnimationTypeClose]; 436 | 437 | NSAssert(durations.count >= animationItemViews.count, @"wrong override func animationDuration(itemIndex:NSInteger, type:AnimationType)-> NSTimeInterval"); 438 | 439 | for (int index = 0; index < animationItemViews.count; index ++) { 440 | CCRotatedView *animatedView = [[animationItemViews reverseObjectEnumerator] allObjects][index]; 441 | 442 | [animatedView foldingAnimationWithTimingFunctionString:timing from:from to:to duration:durations[index].doubleValue delay:delay hidden:hidden]; 443 | 444 | to = to == 0.f ? M_PI / 2 : 0.f; 445 | from = from == 0.f ? -M_PI / 2 : 0.f; 446 | timing = timing == kCAMediaTimingFunctionEaseIn ? kCAMediaTimingFunctionEaseOut : kCAMediaTimingFunctionEaseIn; 447 | hidden = !hidden; 448 | delay += durations[index].doubleValue; 449 | } 450 | 451 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 452 | self.animationView.alpha = 0; 453 | if (completion) completion(); 454 | }); 455 | 456 | NSMutableArray *tagZeroArray = [NSMutableArray array]; 457 | for (UIView *view in self.animationView.subviews) { 458 | if (view.tag == 0) { 459 | [tagZeroArray addObject:view]; 460 | } 461 | } 462 | 463 | UIView *firstItemView = tagZeroArray.firstObject; 464 | 465 | firstItemView.layer.cornerRadius = 0; 466 | firstItemView.layer.masksToBounds = YES; 467 | 468 | NSNumber *durationNumberFirst = durations.firstObject; 469 | if (durationNumberFirst) { 470 | NSTimeInterval durationFirst = durationNumberFirst.doubleValue; 471 | dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((delay - durationFirst * 2) * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 472 | firstItemView.layer.cornerRadius = self.foregroundView.layer.cornerRadius; 473 | [firstItemView setNeedsDisplay]; 474 | [firstItemView setNeedsLayout]; 475 | }); 476 | } 477 | } 478 | 479 | @end 480 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCell/CCRotatedView.h: -------------------------------------------------------------------------------- 1 | // 2 | // CCRotatedView.h 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CCRotatedView : UIView 12 | 13 | @property (nonatomic, assign) BOOL hiddenAfterAnimation; 14 | @property (nonatomic, strong) CCRotatedView *backView; 15 | 16 | - (void)addBackViewWithHeight:(CGFloat)height color:(UIColor *)color; 17 | 18 | - (void)foldingAnimationWithTimingFunctionString:(NSString *)timing from:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration delay:(NSTimeInterval)delay hidden:(BOOL)hidden; 19 | 20 | - (CATransform3D)rotateTransform3d; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCell/CCRotatedView.m: -------------------------------------------------------------------------------- 1 | // 2 | // CCRotatedView.m 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import "CCRotatedView.h" 10 | 11 | @interface CCRotatedView() 12 | < 13 | CAAnimationDelegate 14 | > 15 | 16 | @end 17 | 18 | @implementation CCRotatedView 19 | 20 | - (void)addBackViewWithHeight:(CGFloat)height color:(UIColor *)color 21 | { 22 | CCRotatedView *view = [[CCRotatedView alloc] initWithFrame:CGRectZero]; 23 | view.backgroundColor = color; 24 | view.layer.anchorPoint = CGPointMake(0.5, 1); 25 | view.layer.transform = [self rotateTransform3d]; 26 | //禁用autoresizing 27 | view.translatesAutoresizingMaskIntoConstraints = false; 28 | self.backView = view; 29 | [self addSubview:view]; 30 | 31 | //添加约束 32 | 33 | NSLayoutConstraint *viewConstraint = [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeHeight relatedBy:NSLayoutRelationEqual toItem:nil attribute:NSLayoutAttributeHeight multiplier:1 constant:height]; 34 | [view addConstraint:viewConstraint]; 35 | 36 | [self addConstraints:@[ 37 | [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTop multiplier:1 constant:self.bounds.size.height - height + height / 2], 38 | [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeLeading multiplier:1 constant:0], 39 | [NSLayoutConstraint constraintWithItem:view attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem:self attribute:NSLayoutAttributeTrailing multiplier:1 constant:0] 40 | ]]; 41 | 42 | } 43 | 44 | - (void)rotatedXByAngle:(CGFloat)angle 45 | { 46 | CATransform3D allTransform = CATransform3DIdentity; 47 | CATransform3D rotateTransform = CATransform3DMakeRotation(angle, 1, 0, 0); 48 | //叠加效果 49 | allTransform = CATransform3DConcat(allTransform, rotateTransform); 50 | allTransform = CATransform3DConcat(allTransform, [self rotateTransform3d]); 51 | self.layer.transform = allTransform; 52 | } 53 | 54 | - (void)foldingAnimationWithTimingFunctionString:(NSString *)timing from:(CGFloat)from to:(CGFloat)to duration:(NSTimeInterval)duration delay:(NSTimeInterval)delay hidden:(BOOL)hidden 55 | { 56 | CABasicAnimation *rotateAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.x"]; 57 | rotateAnimation.timingFunction = [CAMediaTimingFunction functionWithName:timing]; 58 | rotateAnimation.fromValue = @(from); 59 | rotateAnimation.toValue = @(to); 60 | rotateAnimation.duration = duration; 61 | rotateAnimation.delegate = self; 62 | rotateAnimation.fillMode = kCAFillModeForwards; 63 | rotateAnimation.removedOnCompletion = NO; 64 | rotateAnimation.beginTime = CACurrentMediaTime() + delay; 65 | 66 | self.hiddenAfterAnimation = hidden; 67 | [self.layer addAnimation:rotateAnimation forKey:@"rotation.x"]; 68 | } 69 | 70 | #pragma mark CAAnimationDelegate 71 | 72 | - (void)animationDidStart:(CAAnimation *)anim 73 | { 74 | //缓存layer为bitmap 75 | self.layer.shouldRasterize = YES; 76 | self.alpha = 1; 77 | } 78 | 79 | - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag 80 | { 81 | if (self.hiddenAfterAnimation) self.alpha = 0; 82 | 83 | [self.layer removeAllAnimations]; 84 | self.layer.shouldRasterize = NO; 85 | [self rotatedXByAngle:0.f]; 86 | } 87 | 88 | 89 | - (CATransform3D)rotateTransform3d 90 | { 91 | CATransform3D transform = CATransform3DIdentity; 92 | transform.m34 = 2.5 / -2000; 93 | return transform; 94 | } 95 | 96 | @end 97 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCell/UIView+Snapshot.h: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Snapshot.h 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface UIView (Snapshot) 12 | 13 | - (UIImage *)takeSnapshotWithFrame:(CGRect)frame; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCell/UIView+Snapshot.m: -------------------------------------------------------------------------------- 1 | // 2 | // UIView+Snapshot.m 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import "UIView+Snapshot.h" 10 | 11 | @implementation UIView (Snapshot) 12 | 13 | - (UIImage *)takeSnapshotWithFrame:(CGRect)frame 14 | { 15 | 16 | UIGraphicsBeginImageContextWithOptions(self.bounds.size, NO, 1); 17 | [self.layer renderInContext:UIGraphicsGetCurrentContext()]; 18 | UIImage *img = UIGraphicsGetImageFromCurrentImageContext(); 19 | 20 | UIGraphicsEndImageContext(); 21 | 22 | UIImage *resultImg = [UIImage imageWithCGImage:CGImageCreateWithImageInRect(img.CGImage, frame)]; 23 | return resultImg; 24 | } 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 9A3F85C01E5FFA2E003E5528 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85BF1E5FFA2E003E5528 /* main.m */; }; 11 | 9A3F85C31E5FFA2E003E5528 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85C21E5FFA2E003E5528 /* AppDelegate.m */; }; 12 | 9A3F85C61E5FFA2E003E5528 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85C51E5FFA2E003E5528 /* ViewController.m */; }; 13 | 9A3F85C91E5FFA2E003E5528 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9A3F85C71E5FFA2E003E5528 /* Main.storyboard */; }; 14 | 9A3F85CB1E5FFA2E003E5528 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 9A3F85CA1E5FFA2E003E5528 /* Assets.xcassets */; }; 15 | 9A3F85CE1E5FFA2E003E5528 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 9A3F85CC1E5FFA2E003E5528 /* LaunchScreen.storyboard */; }; 16 | 9A3F85D91E5FFA2E003E5528 /* CCFoldCellDemoTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85D81E5FFA2E003E5528 /* CCFoldCellDemoTests.m */; }; 17 | 9A3F85E41E5FFA2E003E5528 /* CCFoldCellDemoUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85E31E5FFA2E003E5528 /* CCFoldCellDemoUITests.m */; }; 18 | 9A3F85F81E5FFA4B003E5528 /* CCFoldCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85F31E5FFA4B003E5528 /* CCFoldCell.m */; }; 19 | 9A3F85F91E5FFA4B003E5528 /* CCRotatedView.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85F51E5FFA4B003E5528 /* CCRotatedView.m */; }; 20 | 9A3F85FA1E5FFA4B003E5528 /* UIView+Snapshot.m in Sources */ = {isa = PBXBuildFile; fileRef = 9A3F85F71E5FFA4B003E5528 /* UIView+Snapshot.m */; }; 21 | 9AFCDC541E5FFC6C00F53BCD /* DemoCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 9AFCDC521E5FFC6C00F53BCD /* DemoCell.m */; }; 22 | 9AFCDC551E5FFC6C00F53BCD /* DemoCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9AFCDC531E5FFC6C00F53BCD /* DemoCell.xib */; }; 23 | /* End PBXBuildFile section */ 24 | 25 | /* Begin PBXContainerItemProxy section */ 26 | 9A3F85D51E5FFA2E003E5528 /* PBXContainerItemProxy */ = { 27 | isa = PBXContainerItemProxy; 28 | containerPortal = 9A3F85B31E5FFA2E003E5528 /* Project object */; 29 | proxyType = 1; 30 | remoteGlobalIDString = 9A3F85BA1E5FFA2E003E5528; 31 | remoteInfo = CCFoldCellDemo; 32 | }; 33 | 9A3F85E01E5FFA2E003E5528 /* PBXContainerItemProxy */ = { 34 | isa = PBXContainerItemProxy; 35 | containerPortal = 9A3F85B31E5FFA2E003E5528 /* Project object */; 36 | proxyType = 1; 37 | remoteGlobalIDString = 9A3F85BA1E5FFA2E003E5528; 38 | remoteInfo = CCFoldCellDemo; 39 | }; 40 | /* End PBXContainerItemProxy section */ 41 | 42 | /* Begin PBXFileReference section */ 43 | 9A3F85BB1E5FFA2E003E5528 /* CCFoldCellDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CCFoldCellDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; 44 | 9A3F85BF1E5FFA2E003E5528 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 45 | 9A3F85C11E5FFA2E003E5528 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 46 | 9A3F85C21E5FFA2E003E5528 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 47 | 9A3F85C41E5FFA2E003E5528 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 48 | 9A3F85C51E5FFA2E003E5528 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 49 | 9A3F85C81E5FFA2E003E5528 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 50 | 9A3F85CA1E5FFA2E003E5528 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 51 | 9A3F85CD1E5FFA2E003E5528 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 52 | 9A3F85CF1E5FFA2E003E5528 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 53 | 9A3F85D41E5FFA2E003E5528 /* CCFoldCellDemoTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CCFoldCellDemoTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 54 | 9A3F85D81E5FFA2E003E5528 /* CCFoldCellDemoTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CCFoldCellDemoTests.m; sourceTree = ""; }; 55 | 9A3F85DA1E5FFA2E003E5528 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 56 | 9A3F85DF1E5FFA2E003E5528 /* CCFoldCellDemoUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = CCFoldCellDemoUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 57 | 9A3F85E31E5FFA2E003E5528 /* CCFoldCellDemoUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CCFoldCellDemoUITests.m; sourceTree = ""; }; 58 | 9A3F85E51E5FFA2E003E5528 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 59 | 9A3F85F21E5FFA4B003E5528 /* CCFoldCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCFoldCell.h; sourceTree = ""; }; 60 | 9A3F85F31E5FFA4B003E5528 /* CCFoldCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCFoldCell.m; sourceTree = ""; }; 61 | 9A3F85F41E5FFA4B003E5528 /* CCRotatedView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CCRotatedView.h; sourceTree = ""; }; 62 | 9A3F85F51E5FFA4B003E5528 /* CCRotatedView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CCRotatedView.m; sourceTree = ""; }; 63 | 9A3F85F61E5FFA4B003E5528 /* UIView+Snapshot.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIView+Snapshot.h"; sourceTree = ""; }; 64 | 9A3F85F71E5FFA4B003E5528 /* UIView+Snapshot.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIView+Snapshot.m"; sourceTree = ""; }; 65 | 9AFCDC511E5FFC6C00F53BCD /* DemoCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DemoCell.h; sourceTree = ""; }; 66 | 9AFCDC521E5FFC6C00F53BCD /* DemoCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DemoCell.m; sourceTree = ""; }; 67 | 9AFCDC531E5FFC6C00F53BCD /* DemoCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = DemoCell.xib; sourceTree = ""; }; 68 | /* End PBXFileReference section */ 69 | 70 | /* Begin PBXFrameworksBuildPhase section */ 71 | 9A3F85B81E5FFA2E003E5528 /* Frameworks */ = { 72 | isa = PBXFrameworksBuildPhase; 73 | buildActionMask = 2147483647; 74 | files = ( 75 | ); 76 | runOnlyForDeploymentPostprocessing = 0; 77 | }; 78 | 9A3F85D11E5FFA2E003E5528 /* Frameworks */ = { 79 | isa = PBXFrameworksBuildPhase; 80 | buildActionMask = 2147483647; 81 | files = ( 82 | ); 83 | runOnlyForDeploymentPostprocessing = 0; 84 | }; 85 | 9A3F85DC1E5FFA2E003E5528 /* Frameworks */ = { 86 | isa = PBXFrameworksBuildPhase; 87 | buildActionMask = 2147483647; 88 | files = ( 89 | ); 90 | runOnlyForDeploymentPostprocessing = 0; 91 | }; 92 | /* End PBXFrameworksBuildPhase section */ 93 | 94 | /* Begin PBXGroup section */ 95 | 9A3F85B21E5FFA2E003E5528 = { 96 | isa = PBXGroup; 97 | children = ( 98 | 9A3F85F11E5FFA4B003E5528 /* CCFoldCell */, 99 | 9A3F85BD1E5FFA2E003E5528 /* CCFoldCellDemo */, 100 | 9A3F85D71E5FFA2E003E5528 /* CCFoldCellDemoTests */, 101 | 9A3F85E21E5FFA2E003E5528 /* CCFoldCellDemoUITests */, 102 | 9A3F85BC1E5FFA2E003E5528 /* Products */, 103 | ); 104 | sourceTree = ""; 105 | }; 106 | 9A3F85BC1E5FFA2E003E5528 /* Products */ = { 107 | isa = PBXGroup; 108 | children = ( 109 | 9A3F85BB1E5FFA2E003E5528 /* CCFoldCellDemo.app */, 110 | 9A3F85D41E5FFA2E003E5528 /* CCFoldCellDemoTests.xctest */, 111 | 9A3F85DF1E5FFA2E003E5528 /* CCFoldCellDemoUITests.xctest */, 112 | ); 113 | name = Products; 114 | sourceTree = ""; 115 | }; 116 | 9A3F85BD1E5FFA2E003E5528 /* CCFoldCellDemo */ = { 117 | isa = PBXGroup; 118 | children = ( 119 | 9A3F85C11E5FFA2E003E5528 /* AppDelegate.h */, 120 | 9A3F85C21E5FFA2E003E5528 /* AppDelegate.m */, 121 | 9A3F85C41E5FFA2E003E5528 /* ViewController.h */, 122 | 9A3F85C51E5FFA2E003E5528 /* ViewController.m */, 123 | 9AFCDC511E5FFC6C00F53BCD /* DemoCell.h */, 124 | 9AFCDC521E5FFC6C00F53BCD /* DemoCell.m */, 125 | 9AFCDC531E5FFC6C00F53BCD /* DemoCell.xib */, 126 | 9A3F85C71E5FFA2E003E5528 /* Main.storyboard */, 127 | 9A3F85CA1E5FFA2E003E5528 /* Assets.xcassets */, 128 | 9A3F85CC1E5FFA2E003E5528 /* LaunchScreen.storyboard */, 129 | 9A3F85CF1E5FFA2E003E5528 /* Info.plist */, 130 | 9A3F85BE1E5FFA2E003E5528 /* Supporting Files */, 131 | ); 132 | path = CCFoldCellDemo; 133 | sourceTree = ""; 134 | }; 135 | 9A3F85BE1E5FFA2E003E5528 /* Supporting Files */ = { 136 | isa = PBXGroup; 137 | children = ( 138 | 9A3F85BF1E5FFA2E003E5528 /* main.m */, 139 | ); 140 | name = "Supporting Files"; 141 | sourceTree = ""; 142 | }; 143 | 9A3F85D71E5FFA2E003E5528 /* CCFoldCellDemoTests */ = { 144 | isa = PBXGroup; 145 | children = ( 146 | 9A3F85D81E5FFA2E003E5528 /* CCFoldCellDemoTests.m */, 147 | 9A3F85DA1E5FFA2E003E5528 /* Info.plist */, 148 | ); 149 | path = CCFoldCellDemoTests; 150 | sourceTree = ""; 151 | }; 152 | 9A3F85E21E5FFA2E003E5528 /* CCFoldCellDemoUITests */ = { 153 | isa = PBXGroup; 154 | children = ( 155 | 9A3F85E31E5FFA2E003E5528 /* CCFoldCellDemoUITests.m */, 156 | 9A3F85E51E5FFA2E003E5528 /* Info.plist */, 157 | ); 158 | path = CCFoldCellDemoUITests; 159 | sourceTree = ""; 160 | }; 161 | 9A3F85F11E5FFA4B003E5528 /* CCFoldCell */ = { 162 | isa = PBXGroup; 163 | children = ( 164 | 9A3F85F21E5FFA4B003E5528 /* CCFoldCell.h */, 165 | 9A3F85F31E5FFA4B003E5528 /* CCFoldCell.m */, 166 | 9A3F85F41E5FFA4B003E5528 /* CCRotatedView.h */, 167 | 9A3F85F51E5FFA4B003E5528 /* CCRotatedView.m */, 168 | 9A3F85F61E5FFA4B003E5528 /* UIView+Snapshot.h */, 169 | 9A3F85F71E5FFA4B003E5528 /* UIView+Snapshot.m */, 170 | ); 171 | path = CCFoldCell; 172 | sourceTree = ""; 173 | }; 174 | /* End PBXGroup section */ 175 | 176 | /* Begin PBXNativeTarget section */ 177 | 9A3F85BA1E5FFA2E003E5528 /* CCFoldCellDemo */ = { 178 | isa = PBXNativeTarget; 179 | buildConfigurationList = 9A3F85E81E5FFA2E003E5528 /* Build configuration list for PBXNativeTarget "CCFoldCellDemo" */; 180 | buildPhases = ( 181 | 9A3F85B71E5FFA2E003E5528 /* Sources */, 182 | 9A3F85B81E5FFA2E003E5528 /* Frameworks */, 183 | 9A3F85B91E5FFA2E003E5528 /* Resources */, 184 | ); 185 | buildRules = ( 186 | ); 187 | dependencies = ( 188 | ); 189 | name = CCFoldCellDemo; 190 | productName = CCFoldCellDemo; 191 | productReference = 9A3F85BB1E5FFA2E003E5528 /* CCFoldCellDemo.app */; 192 | productType = "com.apple.product-type.application"; 193 | }; 194 | 9A3F85D31E5FFA2E003E5528 /* CCFoldCellDemoTests */ = { 195 | isa = PBXNativeTarget; 196 | buildConfigurationList = 9A3F85EB1E5FFA2E003E5528 /* Build configuration list for PBXNativeTarget "CCFoldCellDemoTests" */; 197 | buildPhases = ( 198 | 9A3F85D01E5FFA2E003E5528 /* Sources */, 199 | 9A3F85D11E5FFA2E003E5528 /* Frameworks */, 200 | 9A3F85D21E5FFA2E003E5528 /* Resources */, 201 | ); 202 | buildRules = ( 203 | ); 204 | dependencies = ( 205 | 9A3F85D61E5FFA2E003E5528 /* PBXTargetDependency */, 206 | ); 207 | name = CCFoldCellDemoTests; 208 | productName = CCFoldCellDemoTests; 209 | productReference = 9A3F85D41E5FFA2E003E5528 /* CCFoldCellDemoTests.xctest */; 210 | productType = "com.apple.product-type.bundle.unit-test"; 211 | }; 212 | 9A3F85DE1E5FFA2E003E5528 /* CCFoldCellDemoUITests */ = { 213 | isa = PBXNativeTarget; 214 | buildConfigurationList = 9A3F85EE1E5FFA2E003E5528 /* Build configuration list for PBXNativeTarget "CCFoldCellDemoUITests" */; 215 | buildPhases = ( 216 | 9A3F85DB1E5FFA2E003E5528 /* Sources */, 217 | 9A3F85DC1E5FFA2E003E5528 /* Frameworks */, 218 | 9A3F85DD1E5FFA2E003E5528 /* Resources */, 219 | ); 220 | buildRules = ( 221 | ); 222 | dependencies = ( 223 | 9A3F85E11E5FFA2E003E5528 /* PBXTargetDependency */, 224 | ); 225 | name = CCFoldCellDemoUITests; 226 | productName = CCFoldCellDemoUITests; 227 | productReference = 9A3F85DF1E5FFA2E003E5528 /* CCFoldCellDemoUITests.xctest */; 228 | productType = "com.apple.product-type.bundle.ui-testing"; 229 | }; 230 | /* End PBXNativeTarget section */ 231 | 232 | /* Begin PBXProject section */ 233 | 9A3F85B31E5FFA2E003E5528 /* Project object */ = { 234 | isa = PBXProject; 235 | attributes = { 236 | LastUpgradeCheck = 0810; 237 | ORGANIZATIONNAME = Bref; 238 | TargetAttributes = { 239 | 9A3F85BA1E5FFA2E003E5528 = { 240 | CreatedOnToolsVersion = 8.1; 241 | ProvisioningStyle = Automatic; 242 | }; 243 | 9A3F85D31E5FFA2E003E5528 = { 244 | CreatedOnToolsVersion = 8.1; 245 | ProvisioningStyle = Automatic; 246 | TestTargetID = 9A3F85BA1E5FFA2E003E5528; 247 | }; 248 | 9A3F85DE1E5FFA2E003E5528 = { 249 | CreatedOnToolsVersion = 8.1; 250 | ProvisioningStyle = Automatic; 251 | TestTargetID = 9A3F85BA1E5FFA2E003E5528; 252 | }; 253 | }; 254 | }; 255 | buildConfigurationList = 9A3F85B61E5FFA2E003E5528 /* Build configuration list for PBXProject "CCFoldCellDemo" */; 256 | compatibilityVersion = "Xcode 3.2"; 257 | developmentRegion = English; 258 | hasScannedForEncodings = 0; 259 | knownRegions = ( 260 | en, 261 | Base, 262 | ); 263 | mainGroup = 9A3F85B21E5FFA2E003E5528; 264 | productRefGroup = 9A3F85BC1E5FFA2E003E5528 /* Products */; 265 | projectDirPath = ""; 266 | projectRoot = ""; 267 | targets = ( 268 | 9A3F85BA1E5FFA2E003E5528 /* CCFoldCellDemo */, 269 | 9A3F85D31E5FFA2E003E5528 /* CCFoldCellDemoTests */, 270 | 9A3F85DE1E5FFA2E003E5528 /* CCFoldCellDemoUITests */, 271 | ); 272 | }; 273 | /* End PBXProject section */ 274 | 275 | /* Begin PBXResourcesBuildPhase section */ 276 | 9A3F85B91E5FFA2E003E5528 /* Resources */ = { 277 | isa = PBXResourcesBuildPhase; 278 | buildActionMask = 2147483647; 279 | files = ( 280 | 9A3F85CE1E5FFA2E003E5528 /* LaunchScreen.storyboard in Resources */, 281 | 9A3F85CB1E5FFA2E003E5528 /* Assets.xcassets in Resources */, 282 | 9AFCDC551E5FFC6C00F53BCD /* DemoCell.xib in Resources */, 283 | 9A3F85C91E5FFA2E003E5528 /* Main.storyboard in Resources */, 284 | ); 285 | runOnlyForDeploymentPostprocessing = 0; 286 | }; 287 | 9A3F85D21E5FFA2E003E5528 /* Resources */ = { 288 | isa = PBXResourcesBuildPhase; 289 | buildActionMask = 2147483647; 290 | files = ( 291 | ); 292 | runOnlyForDeploymentPostprocessing = 0; 293 | }; 294 | 9A3F85DD1E5FFA2E003E5528 /* Resources */ = { 295 | isa = PBXResourcesBuildPhase; 296 | buildActionMask = 2147483647; 297 | files = ( 298 | ); 299 | runOnlyForDeploymentPostprocessing = 0; 300 | }; 301 | /* End PBXResourcesBuildPhase section */ 302 | 303 | /* Begin PBXSourcesBuildPhase section */ 304 | 9A3F85B71E5FFA2E003E5528 /* Sources */ = { 305 | isa = PBXSourcesBuildPhase; 306 | buildActionMask = 2147483647; 307 | files = ( 308 | 9A3F85FA1E5FFA4B003E5528 /* UIView+Snapshot.m in Sources */, 309 | 9A3F85C61E5FFA2E003E5528 /* ViewController.m in Sources */, 310 | 9A3F85C31E5FFA2E003E5528 /* AppDelegate.m in Sources */, 311 | 9AFCDC541E5FFC6C00F53BCD /* DemoCell.m in Sources */, 312 | 9A3F85F91E5FFA4B003E5528 /* CCRotatedView.m in Sources */, 313 | 9A3F85F81E5FFA4B003E5528 /* CCFoldCell.m in Sources */, 314 | 9A3F85C01E5FFA2E003E5528 /* main.m in Sources */, 315 | ); 316 | runOnlyForDeploymentPostprocessing = 0; 317 | }; 318 | 9A3F85D01E5FFA2E003E5528 /* Sources */ = { 319 | isa = PBXSourcesBuildPhase; 320 | buildActionMask = 2147483647; 321 | files = ( 322 | 9A3F85D91E5FFA2E003E5528 /* CCFoldCellDemoTests.m in Sources */, 323 | ); 324 | runOnlyForDeploymentPostprocessing = 0; 325 | }; 326 | 9A3F85DB1E5FFA2E003E5528 /* Sources */ = { 327 | isa = PBXSourcesBuildPhase; 328 | buildActionMask = 2147483647; 329 | files = ( 330 | 9A3F85E41E5FFA2E003E5528 /* CCFoldCellDemoUITests.m in Sources */, 331 | ); 332 | runOnlyForDeploymentPostprocessing = 0; 333 | }; 334 | /* End PBXSourcesBuildPhase section */ 335 | 336 | /* Begin PBXTargetDependency section */ 337 | 9A3F85D61E5FFA2E003E5528 /* PBXTargetDependency */ = { 338 | isa = PBXTargetDependency; 339 | target = 9A3F85BA1E5FFA2E003E5528 /* CCFoldCellDemo */; 340 | targetProxy = 9A3F85D51E5FFA2E003E5528 /* PBXContainerItemProxy */; 341 | }; 342 | 9A3F85E11E5FFA2E003E5528 /* PBXTargetDependency */ = { 343 | isa = PBXTargetDependency; 344 | target = 9A3F85BA1E5FFA2E003E5528 /* CCFoldCellDemo */; 345 | targetProxy = 9A3F85E01E5FFA2E003E5528 /* PBXContainerItemProxy */; 346 | }; 347 | /* End PBXTargetDependency section */ 348 | 349 | /* Begin PBXVariantGroup section */ 350 | 9A3F85C71E5FFA2E003E5528 /* Main.storyboard */ = { 351 | isa = PBXVariantGroup; 352 | children = ( 353 | 9A3F85C81E5FFA2E003E5528 /* Base */, 354 | ); 355 | name = Main.storyboard; 356 | sourceTree = ""; 357 | }; 358 | 9A3F85CC1E5FFA2E003E5528 /* LaunchScreen.storyboard */ = { 359 | isa = PBXVariantGroup; 360 | children = ( 361 | 9A3F85CD1E5FFA2E003E5528 /* Base */, 362 | ); 363 | name = LaunchScreen.storyboard; 364 | sourceTree = ""; 365 | }; 366 | /* End PBXVariantGroup section */ 367 | 368 | /* Begin XCBuildConfiguration section */ 369 | 9A3F85E61E5FFA2E003E5528 /* Debug */ = { 370 | isa = XCBuildConfiguration; 371 | buildSettings = { 372 | ALWAYS_SEARCH_USER_PATHS = NO; 373 | CLANG_ANALYZER_NONNULL = YES; 374 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 375 | CLANG_CXX_LIBRARY = "libc++"; 376 | CLANG_ENABLE_MODULES = YES; 377 | CLANG_ENABLE_OBJC_ARC = YES; 378 | CLANG_WARN_BOOL_CONVERSION = YES; 379 | CLANG_WARN_CONSTANT_CONVERSION = YES; 380 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 381 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 382 | CLANG_WARN_EMPTY_BODY = YES; 383 | CLANG_WARN_ENUM_CONVERSION = YES; 384 | CLANG_WARN_INFINITE_RECURSION = YES; 385 | CLANG_WARN_INT_CONVERSION = YES; 386 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 387 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 388 | CLANG_WARN_UNREACHABLE_CODE = YES; 389 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 390 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 391 | COPY_PHASE_STRIP = NO; 392 | DEBUG_INFORMATION_FORMAT = dwarf; 393 | ENABLE_STRICT_OBJC_MSGSEND = YES; 394 | ENABLE_TESTABILITY = YES; 395 | GCC_C_LANGUAGE_STANDARD = gnu99; 396 | GCC_DYNAMIC_NO_PIC = NO; 397 | GCC_NO_COMMON_BLOCKS = YES; 398 | GCC_OPTIMIZATION_LEVEL = 0; 399 | GCC_PREPROCESSOR_DEFINITIONS = ( 400 | "DEBUG=1", 401 | "$(inherited)", 402 | ); 403 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 404 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 405 | GCC_WARN_UNDECLARED_SELECTOR = YES; 406 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 407 | GCC_WARN_UNUSED_FUNCTION = YES; 408 | GCC_WARN_UNUSED_VARIABLE = YES; 409 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 410 | MTL_ENABLE_DEBUG_INFO = YES; 411 | ONLY_ACTIVE_ARCH = YES; 412 | SDKROOT = iphoneos; 413 | TARGETED_DEVICE_FAMILY = "1,2"; 414 | }; 415 | name = Debug; 416 | }; 417 | 9A3F85E71E5FFA2E003E5528 /* Release */ = { 418 | isa = XCBuildConfiguration; 419 | buildSettings = { 420 | ALWAYS_SEARCH_USER_PATHS = NO; 421 | CLANG_ANALYZER_NONNULL = YES; 422 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 423 | CLANG_CXX_LIBRARY = "libc++"; 424 | CLANG_ENABLE_MODULES = YES; 425 | CLANG_ENABLE_OBJC_ARC = YES; 426 | CLANG_WARN_BOOL_CONVERSION = YES; 427 | CLANG_WARN_CONSTANT_CONVERSION = YES; 428 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 429 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 430 | CLANG_WARN_EMPTY_BODY = YES; 431 | CLANG_WARN_ENUM_CONVERSION = YES; 432 | CLANG_WARN_INFINITE_RECURSION = YES; 433 | CLANG_WARN_INT_CONVERSION = YES; 434 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 435 | CLANG_WARN_SUSPICIOUS_MOVES = YES; 436 | CLANG_WARN_UNREACHABLE_CODE = YES; 437 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 438 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 439 | COPY_PHASE_STRIP = NO; 440 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 441 | ENABLE_NS_ASSERTIONS = NO; 442 | ENABLE_STRICT_OBJC_MSGSEND = YES; 443 | GCC_C_LANGUAGE_STANDARD = gnu99; 444 | GCC_NO_COMMON_BLOCKS = YES; 445 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 446 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 447 | GCC_WARN_UNDECLARED_SELECTOR = YES; 448 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 449 | GCC_WARN_UNUSED_FUNCTION = YES; 450 | GCC_WARN_UNUSED_VARIABLE = YES; 451 | IPHONEOS_DEPLOYMENT_TARGET = 10.1; 452 | MTL_ENABLE_DEBUG_INFO = NO; 453 | SDKROOT = iphoneos; 454 | TARGETED_DEVICE_FAMILY = "1,2"; 455 | VALIDATE_PRODUCT = YES; 456 | }; 457 | name = Release; 458 | }; 459 | 9A3F85E91E5FFA2E003E5528 /* Debug */ = { 460 | isa = XCBuildConfiguration; 461 | buildSettings = { 462 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 463 | INFOPLIST_FILE = CCFoldCellDemo/Info.plist; 464 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 465 | PRODUCT_BUNDLE_IDENTIFIER = Bref.CCFoldCellDemo; 466 | PRODUCT_NAME = "$(TARGET_NAME)"; 467 | }; 468 | name = Debug; 469 | }; 470 | 9A3F85EA1E5FFA2E003E5528 /* Release */ = { 471 | isa = XCBuildConfiguration; 472 | buildSettings = { 473 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 474 | INFOPLIST_FILE = CCFoldCellDemo/Info.plist; 475 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 476 | PRODUCT_BUNDLE_IDENTIFIER = Bref.CCFoldCellDemo; 477 | PRODUCT_NAME = "$(TARGET_NAME)"; 478 | }; 479 | name = Release; 480 | }; 481 | 9A3F85EC1E5FFA2E003E5528 /* Debug */ = { 482 | isa = XCBuildConfiguration; 483 | buildSettings = { 484 | BUNDLE_LOADER = "$(TEST_HOST)"; 485 | INFOPLIST_FILE = CCFoldCellDemoTests/Info.plist; 486 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 487 | PRODUCT_BUNDLE_IDENTIFIER = Bref.CCFoldCellDemoTests; 488 | PRODUCT_NAME = "$(TARGET_NAME)"; 489 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCFoldCellDemo.app/CCFoldCellDemo"; 490 | }; 491 | name = Debug; 492 | }; 493 | 9A3F85ED1E5FFA2E003E5528 /* Release */ = { 494 | isa = XCBuildConfiguration; 495 | buildSettings = { 496 | BUNDLE_LOADER = "$(TEST_HOST)"; 497 | INFOPLIST_FILE = CCFoldCellDemoTests/Info.plist; 498 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 499 | PRODUCT_BUNDLE_IDENTIFIER = Bref.CCFoldCellDemoTests; 500 | PRODUCT_NAME = "$(TARGET_NAME)"; 501 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/CCFoldCellDemo.app/CCFoldCellDemo"; 502 | }; 503 | name = Release; 504 | }; 505 | 9A3F85EF1E5FFA2E003E5528 /* Debug */ = { 506 | isa = XCBuildConfiguration; 507 | buildSettings = { 508 | INFOPLIST_FILE = CCFoldCellDemoUITests/Info.plist; 509 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 510 | PRODUCT_BUNDLE_IDENTIFIER = Bref.CCFoldCellDemoUITests; 511 | PRODUCT_NAME = "$(TARGET_NAME)"; 512 | TEST_TARGET_NAME = CCFoldCellDemo; 513 | }; 514 | name = Debug; 515 | }; 516 | 9A3F85F01E5FFA2E003E5528 /* Release */ = { 517 | isa = XCBuildConfiguration; 518 | buildSettings = { 519 | INFOPLIST_FILE = CCFoldCellDemoUITests/Info.plist; 520 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 521 | PRODUCT_BUNDLE_IDENTIFIER = Bref.CCFoldCellDemoUITests; 522 | PRODUCT_NAME = "$(TARGET_NAME)"; 523 | TEST_TARGET_NAME = CCFoldCellDemo; 524 | }; 525 | name = Release; 526 | }; 527 | /* End XCBuildConfiguration section */ 528 | 529 | /* Begin XCConfigurationList section */ 530 | 9A3F85B61E5FFA2E003E5528 /* Build configuration list for PBXProject "CCFoldCellDemo" */ = { 531 | isa = XCConfigurationList; 532 | buildConfigurations = ( 533 | 9A3F85E61E5FFA2E003E5528 /* Debug */, 534 | 9A3F85E71E5FFA2E003E5528 /* Release */, 535 | ); 536 | defaultConfigurationIsVisible = 0; 537 | defaultConfigurationName = Release; 538 | }; 539 | 9A3F85E81E5FFA2E003E5528 /* Build configuration list for PBXNativeTarget "CCFoldCellDemo" */ = { 540 | isa = XCConfigurationList; 541 | buildConfigurations = ( 542 | 9A3F85E91E5FFA2E003E5528 /* Debug */, 543 | 9A3F85EA1E5FFA2E003E5528 /* Release */, 544 | ); 545 | defaultConfigurationIsVisible = 0; 546 | defaultConfigurationName = Release; 547 | }; 548 | 9A3F85EB1E5FFA2E003E5528 /* Build configuration list for PBXNativeTarget "CCFoldCellDemoTests" */ = { 549 | isa = XCConfigurationList; 550 | buildConfigurations = ( 551 | 9A3F85EC1E5FFA2E003E5528 /* Debug */, 552 | 9A3F85ED1E5FFA2E003E5528 /* Release */, 553 | ); 554 | defaultConfigurationIsVisible = 0; 555 | defaultConfigurationName = Release; 556 | }; 557 | 9A3F85EE1E5FFA2E003E5528 /* Build configuration list for PBXNativeTarget "CCFoldCellDemoUITests" */ = { 558 | isa = XCConfigurationList; 559 | buildConfigurations = ( 560 | 9A3F85EF1E5FFA2E003E5528 /* Debug */, 561 | 9A3F85F01E5FFA2E003E5528 /* Release */, 562 | ); 563 | defaultConfigurationIsVisible = 0; 564 | defaultConfigurationName = Release; 565 | }; 566 | /* End XCConfigurationList section */ 567 | }; 568 | rootObject = 9A3F85B31E5FFA2E003E5528 /* Project object */; 569 | } 570 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo.xcodeproj/project.xcworkspace/xcuserdata/ehome.xcuserdatad/UserInterfaceState.xcuserstate: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo.xcodeproj/project.xcworkspace/xcuserdata/ehome.xcuserdatad/UserInterfaceState.xcuserstate -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo.xcodeproj/xcuserdata/ehome.xcuserdatad/xcschemes/CCFoldCellDemo.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 24 | 25 | 30 | 31 | 33 | 39 | 40 | 41 | 43 | 49 | 50 | 51 | 52 | 53 | 59 | 60 | 61 | 62 | 63 | 64 | 74 | 76 | 82 | 83 | 84 | 85 | 86 | 87 | 93 | 95 | 101 | 102 | 103 | 104 | 106 | 107 | 110 | 111 | 112 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo.xcodeproj/xcuserdata/ehome.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | CCFoldCellDemo.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | SuppressBuildableAutocreation 14 | 15 | 9A3F85BA1E5FFA2E003E5528 16 | 17 | primary 18 | 19 | 20 | 9A3F85D31E5FFA2E003E5528 21 | 22 | primary 23 | 24 | 25 | 9A3F85DE1E5FFA2E003E5528 26 | 27 | primary 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/24. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface AppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/24. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | 11 | @interface AppDelegate () 12 | 13 | @end 14 | 15 | @implementation AppDelegate 16 | 17 | 18 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 19 | // Override point for customization after application launch. 20 | return YES; 21 | } 22 | 23 | 24 | - (void)applicationWillResignActive:(UIApplication *)application { 25 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 26 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 27 | } 28 | 29 | 30 | - (void)applicationDidEnterBackground:(UIApplication *)application { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | 36 | - (void)applicationWillEnterForeground:(UIApplication *)application { 37 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 38 | } 39 | 40 | 41 | - (void)applicationDidBecomeActive:(UIApplication *)application { 42 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 43 | } 44 | 45 | 46 | - (void)applicationWillTerminate:(UIApplication *)application { 47 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 48 | } 49 | 50 | 51 | @end 52 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/arrow.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "iphone", 9 | "filename" : "arrow.pdf", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "iphone", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/arrow.imageset/arrow.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/arrow.imageset/arrow.pdf -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "background.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/background.imageset/background.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/background.imageset/background.png -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/burger.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "iphone", 9 | "filename" : "burger.pdf", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "iphone", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/burger.imageset/burger.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/burger.imageset/burger.pdf -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/dots.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone" 5 | }, 6 | { 7 | "idiom" : "iphone", 8 | "scale" : "1x" 9 | }, 10 | { 11 | "idiom" : "iphone", 12 | "filename" : "dots.pdf", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "idiom" : "iphone", 17 | "scale" : "3x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/dots.imageset/dots.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/dots.imageset/dots.pdf -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/image.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "filename" : "image.png", 10 | "scale" : "2x" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/image.imageset/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/image.imageset/image.png -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/photo.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone" 5 | }, 6 | { 7 | "idiom" : "iphone", 8 | "scale" : "1x" 9 | }, 10 | { 11 | "idiom" : "iphone", 12 | "filename" : "photo.pdf", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "idiom" : "iphone", 17 | "scale" : "3x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/photo.imageset/photo.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/photo.imageset/photo.pdf -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/stars.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone" 5 | }, 6 | { 7 | "idiom" : "iphone", 8 | "scale" : "1x" 9 | }, 10 | { 11 | "idiom" : "iphone", 12 | "filename" : "stars.pdf", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "idiom" : "iphone", 17 | "scale" : "3x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/stars.imageset/stars.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/CCFoldCellDemo/CCFoldCellDemo/Assets.xcassets/stars.imageset/stars.pdf -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/DemoCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell.h 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "CCFoldCell.h" 11 | 12 | @interface DemoCell : CCFoldCell 13 | 14 | @property (nonatomic, weak) IBOutlet UILabel *closeNumberLabel; 15 | 16 | @property (nonatomic, weak) IBOutlet UILabel *openNumberLabel; 17 | 18 | - (void)setNumber:(NSInteger)number; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/DemoCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // DemoCell.m 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import "DemoCell.h" 10 | 11 | @implementation DemoCell 12 | 13 | - (void)awakeFromNib { 14 | [super awakeFromNib]; 15 | 16 | self.foregroundView.layer.cornerRadius = 10; 17 | self.foregroundView.layer.masksToBounds = YES; 18 | } 19 | 20 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 21 | [super setSelected:selected animated:animated]; 22 | 23 | // Configure the view for the selected state 24 | } 25 | 26 | - (void)setNumber:(NSInteger)number 27 | { 28 | self.openNumberLabel.text = @(number).stringValue; 29 | self.closeNumberLabel.text = @(number).stringValue; 30 | } 31 | 32 | - (NSTimeInterval)animationDurationWithItemIndex:(NSInteger)itemIndex animationType:(AnimationType)type 33 | { 34 | NSArray *array = @[@(0.5f),@(.25f),@(.25f)]; 35 | return array[itemIndex].doubleValue; 36 | } 37 | 38 | @end 39 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/DemoCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | OpenSans-Light 14 | 15 | 16 | OpenSans 17 | 18 | 19 | OpenSans-Semibold 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 44 | 50 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 88 | 94 | 95 | 96 | 97 | 103 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 127 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 151 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 212 | 218 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 256 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 281 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 305 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 353 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 388 | 394 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 423 | 429 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 499 | 505 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | 522 | 523 | 524 | 525 | 526 | 527 | 528 | 534 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | 547 | 548 | 549 | 550 | 551 | 552 | 553 | 554 | 555 | 556 | 557 | 558 | 559 | 560 | 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 591 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | UIInterfaceOrientationLandscapeLeft 35 | UIInterfaceOrientationLandscapeRight 36 | 37 | UISupportedInterfaceOrientations~ipad 38 | 39 | UIInterfaceOrientationPortrait 40 | UIInterfaceOrientationPortraitUpsideDown 41 | UIInterfaceOrientationLandscapeLeft 42 | UIInterfaceOrientationLandscapeRight 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/24. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ViewController : UIViewController 12 | 13 | 14 | @end 15 | 16 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/ViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/23. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import "ViewController.h" 10 | #import "DemoCell.h" 11 | 12 | #define kCloseCellHeight 179.f 13 | #define kOpenCellHeight 488.f 14 | #define kRowsCount 10 15 | 16 | @interface ViewController () 17 | < 18 | UITableViewDelegate, 19 | UITableViewDataSource 20 | > 21 | 22 | @property (nonatomic, strong) UITableView *tableView; 23 | 24 | @property (nonatomic, strong) NSMutableArray *cellHeights; 25 | 26 | @end 27 | 28 | @implementation ViewController 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | // Do any additional setup after loading the view, typically from a nib. 33 | [self.view addSubview:self.tableView]; 34 | 35 | [self createCellHeightsArray]; 36 | self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background"]]; 37 | 38 | } 39 | 40 | - (void)createCellHeightsArray 41 | { 42 | for (int i = 0; i < kRowsCount; i ++) { 43 | [self.cellHeights addObject:@(kCloseCellHeight)]; 44 | } 45 | } 46 | 47 | #pragma mark - UITableViewDelegate && UITableViewDataSource 48 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 49 | { 50 | return kRowsCount; 51 | } 52 | 53 | - (void)tableView:(UITableView *)tableView willDisplayCell:(DemoCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 54 | { 55 | if (![cell isKindOfClass:[DemoCell class]]) return; 56 | 57 | cell.backgroundColor = [UIColor clearColor]; 58 | 59 | CGFloat cellHeight = self.cellHeights[indexPath.row].floatValue; 60 | if (cellHeight == kCloseCellHeight) { 61 | [cell selectedAnimationByIsSelected:NO animated:NO completion:nil]; 62 | }else 63 | { 64 | [cell selectedAnimationByIsSelected:YES animated:NO completion:nil]; 65 | } 66 | 67 | [cell setNumber:indexPath.row]; 68 | } 69 | 70 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 71 | { 72 | DemoCell *cell = [tableView dequeueReusableCellWithIdentifier:@"DemoCell" forIndexPath:indexPath]; 73 | return cell; 74 | } 75 | 76 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 77 | { 78 | return self.cellHeights[indexPath.row].floatValue; 79 | } 80 | 81 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 82 | { 83 | DemoCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 84 | 85 | if (![cell isKindOfClass:[DemoCell class]]) return; 86 | 87 | if (cell.isAnimating) return; 88 | 89 | NSTimeInterval duration = 0.f; 90 | 91 | CGFloat cellHeight = self.cellHeights[indexPath.row].floatValue; 92 | 93 | if (cellHeight == kCloseCellHeight) { 94 | self.cellHeights[indexPath.row] = @(kOpenCellHeight); 95 | [cell selectedAnimationByIsSelected:YES animated:YES completion:nil]; 96 | duration = 1.f; 97 | }else 98 | { 99 | self.cellHeights[indexPath.row] = @(kCloseCellHeight); 100 | [cell selectedAnimationByIsSelected:NO animated:YES completion:nil]; 101 | duration = 1.f; 102 | } 103 | 104 | [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 105 | [tableView beginUpdates]; 106 | [tableView endUpdates]; 107 | } completion:nil]; 108 | 109 | } 110 | 111 | #pragma mark - Getter && Setter 112 | - (UITableView *)tableView 113 | { 114 | if (!_tableView) { 115 | _tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain]; 116 | _tableView.delegate = self; 117 | _tableView.dataSource = self; 118 | [_tableView setSeparatorStyle:UITableViewCellSeparatorStyleNone]; 119 | [_tableView registerNib:[UINib nibWithNibName:@"DemoCell" bundle:nil] forCellReuseIdentifier:@"DemoCell"]; 120 | } 121 | return _tableView; 122 | } 123 | 124 | - (NSMutableArray *)cellHeights 125 | { 126 | if (!_cellHeights) { 127 | _cellHeights = [NSMutableArray array]; 128 | } 129 | return _cellHeights; 130 | } 131 | @end 132 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemo/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // CCFoldCellDemo 4 | // 5 | // Created by eHome on 17/2/24. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemoTests/CCFoldCellDemoTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CCFoldCellDemoTests.m 3 | // CCFoldCellDemoTests 4 | // 5 | // Created by eHome on 17/2/24. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CCFoldCellDemoTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation CCFoldCellDemoTests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | // Put setup code here. This method is called before the invocation of each test method in the class. 20 | } 21 | 22 | - (void)tearDown { 23 | // Put teardown code here. This method is called after the invocation of each test method in the class. 24 | [super tearDown]; 25 | } 26 | 27 | - (void)testExample { 28 | // This is an example of a functional test case. 29 | // Use XCTAssert and related functions to verify your tests produce the correct results. 30 | } 31 | 32 | - (void)testPerformanceExample { 33 | // This is an example of a performance test case. 34 | [self measureBlock:^{ 35 | // Put the code you want to measure the time of here. 36 | }]; 37 | } 38 | 39 | @end 40 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemoTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemoUITests/CCFoldCellDemoUITests.m: -------------------------------------------------------------------------------- 1 | // 2 | // CCFoldCellDemoUITests.m 3 | // CCFoldCellDemoUITests 4 | // 5 | // Created by eHome on 17/2/24. 6 | // Copyright © 2017年 Bref. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface CCFoldCellDemoUITests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation CCFoldCellDemoUITests 16 | 17 | - (void)setUp { 18 | [super setUp]; 19 | 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | 22 | // In UI tests it is usually best to stop immediately when a failure occurs. 23 | self.continueAfterFailure = NO; 24 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 25 | [[[XCUIApplication alloc] init] launch]; 26 | 27 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 28 | } 29 | 30 | - (void)tearDown { 31 | // Put teardown code here. This method is called after the invocation of each test method in the class. 32 | [super tearDown]; 33 | } 34 | 35 | - (void)testExample { 36 | // Use recording to get started writing UI tests. 37 | // Use XCTAssert and related functions to verify your tests produce the correct results. 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /CCFoldCellDemo/CCFoldCellDemoUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # CCFoldCell 2 | Cell折叠动效(OC实现) 3 | 之前在https://github.com/Ramotion/folding-cell 看到了用Swift实现的很炫酷的Cell折叠效果,准备用在公司的项目里面,可惜公司的项目是OC实现,所以,自己动手丰衣足食,我用OC实现了同样的效果 4 | 5 | #### 如果觉得有用,不妨给个Star呗~ 6 | 7 | ### 项目演示 8 | ![image](https://github.com/bref-Chan/CCFoldCell/blob/master/image/CCFoldCell.gif) 9 | 10 | 11 | ### 使用方法 12 | 13 | #### Cell Xib 设置 14 | 15 | 首先,下载Demo,把CCFoldCell文件夹拖入你的工程,创建一个新的Cell继承CCFoldCell,新Cell必须要用Xib. 16 | 17 | 然后,在Xib中选中你的Cell 18 | 19 | 20 | ![image](https://github.com/bref-Chan/CCFoldCell/blob/master/image/CheckCell.png) 21 | 22 | 23 | 在右边属性设置里面设置FoldCell属性 24 | 25 | 26 | ![image](https://github.com/bref-Chan/CCFoldCell/blob/master/image/SetCellProperty.png) 27 | 28 | 29 | >Item Count属性表示翻转动画时,你的内容视图分成多少块翻转视图来进行翻转,值越大,则每块翻转视图越小,反之亦然.注意,值必须设置成2以上 30 | >BackViewColor属性表示你的翻转视图的背后的颜色是什么. 31 | 32 | 然后用AutoLayout进行Cell的布局,布局的规范是,翻转前的视图称为Foreground视图,将翻转完成时显示的视图称为Contener视图 33 | 所以你需要在Cell中布局2个视图,注意2个视图之间不能有任何的相关约束,顶部约束都必须相对于Cell的contentView来进行 34 | 35 | 36 | ![image](https://github.com/bref-Chan/CCFoldCell/blob/master/image/2view.png) 37 | 38 | 39 | 然后分别将这2个视图与containerView和foregroundView Outlets绑定,然后将2个视图相对于Cell的contentView的顶部约束和 containerViewTop 和 foregroundViewTop Outlets绑定 40 | 41 | 42 | ![image](https://github.com/bref-Chan/CCFoldCell/blob/master/image/bindOutlets.png) 43 | 44 | 45 | #### Cell 方法重写 46 | 47 | 接下来在Cell的.m文件中重写父类 48 | ``` 49 | - (NSTimeInterval)animationDurationWithItemIndex:(NSInteger)itemIndex animationType:(AnimationType)type; 50 | ``` 51 | 方法,里面返回的是每次翻转的用时,用NSNumber装起来放入数组返回,例如Demo中的翻转用时返回的是 52 | ``` 53 | - (NSTimeInterval)animationDurationWithItemIndex:(NSInteger)itemIndex animationType:(AnimationType)type 54 | { 55 | NSArray *array = @[@(0.5f),@(.25f),@(.25f)]; 56 | return array[itemIndex].doubleValue; 57 | } 58 | ``` 59 | 那么,Cell的设置就已经完成了,现在讲解的是在视图控制器中如何让Cell进行动画 60 | 61 | #### 动画的开始时机 62 | 63 | 在UITableView的 64 | 65 | ``` 66 | - (void)tableView:(UITableView *)tableView willDisplayCell:(DemoCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath; 67 | 68 | ``` 69 | 70 | 中进行Cell样式的展示,根据Cell的高度来判断Cell是否进行了翻转,具体代码为 71 | 72 | ``` 73 | - (void)tableView:(UITableView *)tableView willDisplayCell:(DemoCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath 74 | { 75 | if (![cell isKindOfClass:[DemoCell class]]) return; 76 | 77 | cell.backgroundColor = [UIColor clearColor]; 78 | 79 | CGFloat cellHeight = self.cellHeights[indexPath.row].floatValue; 80 | if (cellHeight == kCloseCellHeight) { 81 | [cell selectedAnimationByIsSelected:NO animated:NO completion:nil]; 82 | }else 83 | { 84 | [cell selectedAnimationByIsSelected:YES animated:NO completion:nil]; 85 | } 86 | 87 | [cell setNumber:indexPath.row]; 88 | } 89 | ``` 90 | 91 | 然后在UITableViewDelegate 92 | 93 | ``` 94 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath; 95 | ``` 96 | 97 | 中进行Cell的动画触发 98 | 使用Cell的 99 | 100 | ``` 101 | - (void)selectedAnimationByIsSelected:(BOOL)isSelected animated:(BOOL)animated completion:(void(^)())completion; 102 | ``` 103 | 104 | 方法来设置Cell是否是翻转状态,是否进行动画. 105 | 106 | Demo中的实现为 107 | 108 | ``` 109 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 110 | { 111 | DemoCell *cell = [tableView cellForRowAtIndexPath:indexPath]; 112 | 113 | if (![cell isKindOfClass:[DemoCell class]]) return; 114 | 115 | if (cell.isAnimating) return; 116 | 117 | NSTimeInterval duration = 0.f; 118 | 119 | CGFloat cellHeight = self.cellHeights[indexPath.row].floatValue; 120 | 121 | if (cellHeight == kCloseCellHeight) { 122 | self.cellHeights[indexPath.row] = @(kOpenCellHeight); 123 | [cell selectedAnimationByIsSelected:YES animated:YES completion:nil]; 124 | duration = 1.f; 125 | }else 126 | { 127 | self.cellHeights[indexPath.row] = @(kCloseCellHeight); 128 | [cell selectedAnimationByIsSelected:NO animated:YES completion:nil]; 129 | duration = 1.f; 130 | } 131 | 132 | [UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveEaseOut animations:^{ 133 | [tableView beginUpdates]; 134 | [tableView endUpdates]; 135 | } completion:nil]; 136 | 137 | } 138 | ``` 139 |     140 | 141 | 142 | ### 大功告成 143 |   144 | 现在就可以运行项目,欣赏流畅的Cell折叠效果了 145 | -------------------------------------------------------------------------------- /image/2view.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/image/2view.png -------------------------------------------------------------------------------- /image/CCFoldCell.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/image/CCFoldCell.gif -------------------------------------------------------------------------------- /image/CheckCell.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/image/CheckCell.png -------------------------------------------------------------------------------- /image/SetCellProperty.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/image/SetCellProperty.png -------------------------------------------------------------------------------- /image/avatar.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/image/avatar.png -------------------------------------------------------------------------------- /image/bindOutlets.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/brefchan/CCFoldCell/8f52736c215689f220f0bcec78f28d806e6052cb/image/bindOutlets.png --------------------------------------------------------------------------------