// // ABSpringDemoViewController.m // Springy // #import "ABSpringDemoViewController.h" @interface ABSpringDemoViewController () { UITableView *_tableView; CADisplayLink *_displayLink; UIPanGestureRecognizer *_panGestureRecognizer_; NSMutableArray *_objects; CGFloat _panOrigin; CGPoint _panPosition; CGPoint _panTranslation; BOOL _isDragging; } @end @implementation ABSpringDemoViewController - (void)loadView { _tableView = [[UITableView alloc] initWithFrame:CGRectZero]; _tableView.delegate = self; _tableView.dataSource = self; self.view = _tableView; _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(onEnterFrame:)]; [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode]; _objects = [NSMutableArray arrayWithArray:@[ @"Red", @"Orange", @"Yellow", @"Green", @"Cyan", @"Blue", @"Violet", @"Purple", @"Magenta", @"Pink", @"White", @"Gray", @"Black", ]]; _panGestureRecognizer_ = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(panGestureChanged:)]; [self.view addGestureRecognizer:_panGestureRecognizer_]; } - (void)onEnterFrame:(id)sender { if (!_isDragging) return; NSArray *visibleCells = [_tableView visibleCells]; UIView *touchedCell = [self getCellForPosition:_panPosition]; NSUInteger touchedCellIndex = [visibleCells indexOfObject:touchedCell]; [self dragView:touchedCell withTarget:_panTranslation]; for (NSInteger i = touchedCellIndex + 1; i < visibleCells.count; i++) { UITableViewCell *cell = [visibleCells objectAtIndex:i]; UITableViewCell *target = [visibleCells objectAtIndex:i - 1]; [self dragView:cell withTarget:target.frame.origin]; } for (NSInteger i = touchedCellIndex - 1; i >= 0; i--) { UITableViewCell *cell = [visibleCells objectAtIndex:i]; UITableViewCell *target = [visibleCells objectAtIndex:i + 1]; [self dragView:cell withTarget:target.frame.origin]; } } - (void)dragView:(UIView *)view withTarget:(CGPoint)target { CGFloat dx = (target.x - view.frame.origin.x) * 0.3; view.transform = CGAffineTransformTranslate(view.transform, dx, 0); } - (UITableViewCell *)getCellForPosition:(CGPoint)position { NSArray *visibleCells = [_tableView visibleCells]; for (UITableViewCell *cell in visibleCells) { if (CGRectGetMaxY(cell.frame) > position.y) { return cell; } } return [visibleCells lastObject]; } - (void)panGestureChanged:(UIPanGestureRecognizer *)gestureRecognizer { CGPoint translation = [gestureRecognizer translationInView:self.view]; switch (gestureRecognizer.state) { case UIGestureRecognizerStateBegan: _panOrigin = translation.x; _isDragging = YES; case UIGestureRecognizerStateChanged: _panPosition = [gestureRecognizer locationInView:self.view]; _panTranslation = [gestureRecognizer translationInView:self.view]; break; case UIGestureRecognizerStateEnded: { [UIView animateWithDuration:0.4 animations:^{ for (NSIndexPath *index in [_tableView indexPathsForVisibleRows]) { UITableViewCell *cell = [_tableView cellForRowAtIndexPath:index]; CGRect frame = cell.frame; frame.origin.x = 0; cell.frame = frame; } }]; } default: _isDragging = NO; break; } } #pragma mark - Table View - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _objects.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"]; } NSDate *object = _objects[indexPath.row]; cell.textLabel.text = [object description]; cell.selectionStyle = UITableViewCellSelectionStyleNone; return cell; } @end