Skip to content
Browse files

Initial import

  • Loading branch information...
0 parents commit 6a77b63dd71f94d561f9d5fbe83baa1b3b62c0ce Romain Goyet committed Apr 24, 2012
Showing with 196 additions and 0 deletions.
  1. +30 −0 ADLivelyTableView.h
  2. +166 −0 ADLivelyTableView.m
30 ADLivelyTableView.h
@@ -0,0 +1,30 @@
+//
+// ADLivelyTableView.h
+// ADLivelyTableView
+//
+// Created by Romain Goyet on 18/04/12.
+// Copyright (c) 2012 Applidium. All rights reserved.
+//
+
+#import <UIKit/UIKit.h>
+
+extern NSTimeInterval ADLivelyDefaultDuration;
+typedef NSTimeInterval (^ADLivelyTransform)(CALayer * layer, float speed);
+
+extern ADLivelyTransform ADLivelyTransformCurl;
+extern ADLivelyTransform ADLivelyTransformFade;
+extern ADLivelyTransform ADLivelyTransformFan;
+extern ADLivelyTransform ADLivelyTransformFlip;
+extern ADLivelyTransform ADLivelyTransformHelix;
+extern ADLivelyTransform ADLivelyTransformTilt;
+extern ADLivelyTransform ADLivelyTransformWave;
+
+@interface ADLivelyTableView : UITableView <UITableViewDelegate> {
+ id <UITableViewDelegate> _preLivelyDelegate;
+ CGPoint _lastScrollPosition;
+ CGPoint _currentScrollPosition;
+ ADLivelyTransform _transformBlock;
+}
+- (CGPoint)scrollSpeed;
+- (void)setInitialCellTransformBlock:(ADLivelyTransform)block;
+@end
166 ADLivelyTableView.m
@@ -0,0 +1,166 @@
+//
+// ADLivelyTableView.m
+// ADLivelyTableView
+//
+// Created by Romain Goyet on 18/04/12.
+// Copyright (c) 2012 Applidium. All rights reserved.
+//
+
+#import "ADLivelyTableView.h"
+#import <QuartzCore/QuartzCore.h>
+
+NSTimeInterval ADLivelyDefaultDuration = 0.2;
+
+CGFloat CGFloatSign(CGFloat value) {
+ if (value < 0) {
+ return -1.0f;
+ }
+ return 1.0f;
+}
+
+ADLivelyTransform ADLivelyTransformCurl = ^(CALayer * layer, float speed){
+ CATransform3D transform = CATransform3DIdentity;
+ transform.m34 = 1.0 / -500;
+ transform = CATransform3DTranslate(transform, -layer.bounds.size.width/2.0f, 0.0f, 0.0f);
+ transform = CATransform3DRotate(transform, M_PI/2, 0.0f, 1.0f, 0.0f);
+ layer.transform = CATransform3DTranslate(transform, layer.bounds.size.width/2.0f, 0.0f, 0.0f);
+ return ADLivelyDefaultDuration;
+};
+
+ADLivelyTransform ADLivelyTransformFade = ^(CALayer * layer, float speed){
+ if (speed != 0.0f) { // Don't animate the initial state
+ layer.opacity = 1.0f - fabs(speed);
+ }
+ return 2 * ADLivelyDefaultDuration;
+};
+
+ADLivelyTransform ADLivelyTransformFan = ^(CALayer * layer, float speed){
+ CATransform3D transform = CATransform3DIdentity;
+ transform = CATransform3DTranslate(transform, -layer.bounds.size.width/2.0f, 0.0f, 0.0f);
+ transform = CATransform3DRotate(transform, -M_PI/2 * speed, 0.0f, 0.0f, 1.0f);
+ layer.transform = CATransform3DTranslate(transform, layer.bounds.size.width/2.0f, 0.0f, 0.0f);
+ layer.opacity = 1.0f - fabs(speed);
+ return ADLivelyDefaultDuration;
+};
+
+ADLivelyTransform ADLivelyTransformFlip = ^(CALayer * layer, float speed){
+ CATransform3D transform = CATransform3DIdentity;
+ transform = CATransform3DTranslate(transform, 0.0f, CGFloatSign(speed) * layer.bounds.size.height/2.0f, 0.0f);
+ transform = CATransform3DRotate(transform, CGFloatSign(speed) * M_PI/2, 1.0f, 0.0f, 0.0f);
+ layer.transform = CATransform3DTranslate(transform, 0.0f, -CGFloatSign(speed) * layer.bounds.size.height/2.0f, 0.0f);
+ layer.opacity = 1.0f - fabs(speed);
+ return 2 * ADLivelyDefaultDuration;
+};
+
+ADLivelyTransform ADLivelyTransformHelix = ^(CALayer * layer, float speed){
+ CATransform3D transform = CATransform3DIdentity;
+ transform = CATransform3DTranslate(transform, 0.0f, CGFloatSign(speed) * layer.bounds.size.height/2.0f, 0.0f);
+ transform = CATransform3DRotate(transform, M_PI, 0.0f, 1.0f, 0.0f);
+ layer.transform = CATransform3DTranslate(transform, 0.0f, -CGFloatSign(speed) * layer.bounds.size.height/2.0f, 0.0f);
+ layer.opacity = 1.0f - 0.2*fabs(speed);
+ return 2 * ADLivelyDefaultDuration;
+};
+
+ADLivelyTransform ADLivelyTransformTilt = ^(CALayer * layer, float speed){
+ if (speed != 0.0f) { // Don't animate the initial state
+ layer.transform = CATransform3DMakeScale(0.8f, 0.8f, 0.8f);
+ layer.opacity = 1.0f - fabs(speed);
+ }
+ return 2 * ADLivelyDefaultDuration;
+};
+
+ADLivelyTransform ADLivelyTransformWave = ^(CALayer * layer, float speed){
+ if (speed != 0.0f) { // Don't animate the initial state
+ layer.transform = CATransform3DMakeTranslation(-layer.bounds.size.width/2.0f, 0.0f, 0.0f);
+ }
+ return ADLivelyDefaultDuration;
+};
+
+@implementation ADLivelyTableView
+#pragma mark - NSObject
+- (void)dealloc {
+ Block_release(_transformBlock);
+ [super dealloc];
+}
+
+#pragma mark - UIView
++ (Class)layerClass {
+ // This lets us rotate cells in the tableview's 3D space
+ return [CATransformLayer class];
+}
+
+#pragma mark - UITableView
+- (void)setDelegate:(id<UITableViewDelegate>)delegate {
+ // The order here is important, as there seem to be some observing done on setDelegate:
+ if (delegate == self) {
+ _preLivelyDelegate = nil;
+ } else {
+ _preLivelyDelegate = delegate;
+ }
+ [super setDelegate:self];
+}
+
+- (BOOL)respondsToSelector:(SEL)aSelector {
+ return [super respondsToSelector:aSelector] || [_preLivelyDelegate respondsToSelector:aSelector];
+}
+
+- (void)forwardInvocation:(NSInvocation *)anInvocation {
+ if ([_preLivelyDelegate respondsToSelector:[anInvocation selector]]) {
+ [anInvocation invokeWithTarget:_preLivelyDelegate];
+ } else {
+ [super forwardInvocation:anInvocation];
+ }
+}
+
+#pragma mark - ADLivelyTableView
+- (CGPoint)scrollSpeed {
+ return CGPointMake(_lastScrollPosition.x - _currentScrollPosition.x,
+ _lastScrollPosition.y - _currentScrollPosition.y);
+}
+
+- (void)setInitialCellTransformBlock:(ADLivelyTransform)block {
+ CATransform3D transform = CATransform3DIdentity;
+ if (block != nil) {
+ transform.m34 = -1.0/self.bounds.size.width;
+ }
+ self.layer.transform = transform;
+
+ if (block != _transformBlock) {
+ Block_release(_transformBlock);
+ _transformBlock = Block_copy(block);
+ }
+}
+
+#pragma mark - UIScrollViewDelegate
+- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
+ if ([_preLivelyDelegate respondsToSelector:@selector(scrollViewDidScroll:)]) {
+ [_preLivelyDelegate scrollViewDidScroll:scrollView];
+ }
+ _lastScrollPosition = _currentScrollPosition;
+ _currentScrollPosition = [scrollView contentOffset];
+}
+
+#pragma mark - UITableViewDelegate
+- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
+ if ([_preLivelyDelegate respondsToSelector:@selector(tableView:willDisplayCell:forRowAtIndexPath:)]) {
+ [_preLivelyDelegate tableView:tableView willDisplayCell:cell forRowAtIndexPath:indexPath];
+ }
+
+ float speed = self.scrollSpeed.y;
+ float normalizedSpeed = MAX(-1.0f, MIN(1.0f, speed/20.0f));
+
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (_transformBlock) {
+ NSTimeInterval animationDuration = _transformBlock(cell.layer, normalizedSpeed);
+ // The block-based equivalent doesn't play well with iOS 4
+ [UIView beginAnimations:nil context:NULL];
+ [UIView setAnimationDuration:animationDuration];
+ }
+ cell.layer.transform = CATransform3DIdentity;
+ cell.layer.opacity = 1.0f;
+ if (_transformBlock) {
+ [UIView commitAnimations];
+ }
+ });
+}
+@end

0 comments on commit 6a77b63

Please sign in to comment.
Something went wrong with that request. Please try again.