- (void)toggleActivityView:(BOOL)isON { if (!isON) { [activityView stopAnimating]; arrowImage.hidden = NO; } else { [activityView startAnimating]; arrowImage.hidden = YES; [self setStatus:kLoadingStatus]; } } |
if (reloading) return; |
// // EGORefreshTableHeaderView.h // Demo // // Created by Devin Doty on 10/14/09October14. // Copyright 2009 enormego. All rights reserved. // #import <UIKit/UIKit.h&> @interface EGORefreshTableHeaderView : UIView { UILabel *lastUpdatedLabel; UILabel *statusLabel; UIImageView *arrowImage; UIActivityIndicatorView *activityView; BOOL isFlipped; NSDate *lastUpdatedDate; } @property BOOL isFlipped; @property (nonatomic, retain) NSDate *lastUpdatedDate; - (void)flipImageAnimated:(BOOL)animated; - (void)toggleActivityView:(BOOL)isON; - (void)setStatus:(int)status; @end |
// // EGORefreshTableHeaderView.m // Demo // // Created by Devin Doty on 10/14/09October14. // Copyright 2009 enormego. All rights reserved. // #import "EGORefreshTableHeaderView.h" #import <QuartzCore/QuartzCore.h> #define kReleaseToReloadStatus 0 #define kPullToReloadStatus 1 #define kLoadingStatus 2 #define TEXT_COLOR [UIColor colorWithRed:0.341 green:0.737 blue:0.537 alpha:1.0] #define BORDER_COLOR [UIColor colorWithRed:0.341 green:0.737 blue:0.537 alpha:1.0] @implementation EGORefreshTableHeaderView @synthesize isFlipped, lastUpdatedDate; - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { self.backgroundColor = [UIColor colorWithRed:226.0/255.0 green:231.0/255.0 blue:237.0/255.0 alpha:1.0]; lastUpdatedLabel = [[UILabel alloc] initWithFrame: CGRectMake(0.0f, frame.size.height - 30.0f, 320.0f, 20.0f)]; lastUpdatedLabel.font = [UIFont systemFontOfSize:12.0f]; lastUpdatedLabel.textColor = TEXT_COLOR; lastUpdatedLabel.shadowColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; lastUpdatedLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); lastUpdatedLabel.backgroundColor = self.backgroundColor; lastUpdatedLabel.opaque = YES; lastUpdatedLabel.textAlignment = UITextAlignmentCenter; [self addSubview:lastUpdatedLabel]; [lastUpdatedLabel release]; statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 48.0f, 320.0f, 20.0f)]; statusLabel.font = [UIFont boldSystemFontOfSize:13.0f]; statusLabel.textColor = TEXT_COLOR; statusLabel.shadowColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; statusLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); statusLabel.backgroundColor = self.backgroundColor; statusLabel.opaque = YES; statusLabel.textAlignment = UITextAlignmentCenter; [self setStatus:kPullToReloadStatus]; [self addSubview:statusLabel]; [statusLabel release]; arrowImage = [[UIImageView alloc] initWithFrame: CGRectMake(25.0f, frame.size.height - 65.0f, 30.0f, 55.0f)]; arrowImage.contentMode = UIViewContentModeScaleAspectFit; arrowImage.image = [UIImage imageNamed:@"blueArrow.png"]; [arrowImage layer].transform = CATransform3DMakeRotation(M_PI, 0.0f, 0.0f, 1.0f); [self addSubview:arrowImage]; [arrowImage release]; activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle: UIActivityIndicatorViewStyleGray]; activityView.frame = CGRectMake(25.0f, frame.size.height - 38.0f, 20.0f, 20.0f); activityView.hidesWhenStopped = YES; [self addSubview:activityView]; [activityView release]; isFlipped = NO; } return self; } - (void)drawRect:(CGRect)rect{ CGContextRef context = UIGraphicsGetCurrentContext(); CGContextDrawPath(context, kCGPathFillStroke); [BORDER_COLOR setStroke]; CGContextBeginPath(context); CGContextMoveToPoint(context, 0.0f, self.bounds.size.height - 1); CGContextAddLineToPoint(context, self.bounds.size.width, self.bounds.size.height - 1); CGContextStrokePath(context); } - (void)flipImageAnimated:(BOOL)animated { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:animated ? .18 : 0.0]; [arrowImage layer].transform = isFlipped ? CATransform3DMakeRotation(M_PI, 0.0f, 0.0f, 1.0f) : CATransform3DMakeRotation(M_PI * 2, 0.0f, 0.0f, 1.0f); [UIView commitAnimations]; isFlipped = !isFlipped; } - (void)setLastUpdatedDate:(NSDate *)newDate { if (newDate) { if (lastUpdatedDate != newDate) { [lastUpdatedDate release]; } lastUpdatedDate = [newDate retain]; NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; [formatter setDateStyle:NSDateFormatterShortStyle]; [formatter setTimeStyle:NSDateFormatterShortStyle]; lastUpdatedLabel.text = [NSString stringWithFormat: @"Last Updated: %@", [formatter stringFromDate:lastUpdatedDate]]; [formatter release]; } else { lastUpdatedDate = nil; lastUpdatedLabel.text = @"Last Updated: Never"; } } - (void)setStatus:(int)status { switch (status) { case kReleaseToReloadStatus: statusLabel.text = @"Release to refresh..."; break; case kPullToReloadStatus: statusLabel.text = @"Pull down to refresh..."; break; case kLoadingStatus: statusLabel.text = @"Loading..."; break; default: break; } } - (void)toggleActivityView:(BOOL)isON { if (!isON) { [activityView stopAnimating]; arrowImage.hidden = NO; } else { [activityView startAnimating]; arrowImage.hidden = YES; [self setStatus:kLoadingStatus]; } } - (void)dealloc { activityView = nil; statusLabel = nil; arrowImage = nil; lastUpdatedLabel = nil; [super dealloc]; } @end |
// // PullToRefreshTableViewController.h // ASiST // // Created by Oliver on 09.12.09. // Copyright 2009 Drobnik.com. All rights reserved. // #import <UIKit/UIKit.h> #import "EGORefreshTableHeaderView.h" #import "SoundEffect.h" @interface PullToRefreshTableViewController : UITableViewController { EGORefreshTableHeaderView *refreshHeaderView; BOOL checkForRefresh; BOOL reloading; SoundEffect *psst1Sound; SoundEffect *psst2Sound; SoundEffect *popSound; } - (void)dataSourceDidFinishLoadingNewData; - (void) showReloadAnimationAnimated:(BOOL)animated; @end |
// // PullToRefreshTableViewController.m // ASiST // // Created by Oliver on 09.12.09. // Copyright 2009 Drobnik.com. All rights reserved. // #import "PullToRefreshTableViewController.h" #define kReleaseToReloadStatus 0 #define kPullToReloadStatus 1 #define kLoadingStatus 2 @implementation PullToRefreshTableViewController - (void)viewDidLoad { [super viewDidLoad]; refreshHeaderView = [[EGORefreshTableHeaderView alloc] initWithFrame: CGRectMake(0.0f, 0.0f - self.view.bounds.size.height, 320.0f, self.view.bounds.size.height)]; [self.tableView addSubview:refreshHeaderView]; self.tableView.showsVerticalScrollIndicator = YES; // pre-load sounds psst1Sound = [[SoundEffect alloc] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"psst1" ofType:@"wav"]]; psst2Sound = [[SoundEffect alloc] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"psst2" ofType:@"wav"]]; popSound = [[SoundEffect alloc] initWithContentsOfFile: [[NSBundle mainBundle] pathForResource:@"pop" ofType:@"wav"]]; } - (void)dealloc { [psst1Sound release]; [psst2Sound release]; [popSound release]; [refreshHeaderView release]; [super dealloc]; } #pragma mark State Changes - (void) showReloadAnimationAnimated:(BOOL)animated { reloading = YES; [refreshHeaderView toggleActivityView:YES]; if (animated) { [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:0.2]; self.tableView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f); [UIView commitAnimations]; } else { self.tableView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f); } } - (void) reloadTableViewDataSource { NSLog(@"Please override reloadTableViewDataSource"); } - (void)dataSourceDidFinishLoadingNewData { reloading = NO; [refreshHeaderView flipImageAnimated:NO]; [UIView beginAnimations:nil context:NULL]; [UIView setAnimationDuration:.3]; [self.tableView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)]; [refreshHeaderView setStatus:kPullToReloadStatus]; [refreshHeaderView toggleActivityView:NO]; [UIView commitAnimations]; [popSound play]; } #pragma mark Table view methods - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } // Customize the number of rows in the table view. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection: (NSInteger)section { return 0; } // Customize the appearance of table view cells. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier: CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } // Set up the cell... return cell; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath: (NSIndexPath *)indexPath { // Navigation logic may go here. } #pragma mark Scrolling Overrides - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { if (!reloading) { checkForRefresh = YES; // only check offset when dragging } } - (void)scrollViewDidScroll:(UIScrollView *)scrollView { if (reloading) return; if (checkForRefresh) { if (refreshHeaderView.isFlipped && scrollView.contentOffset.y > -65.0f && scrollView.contentOffset.y < 0.0f && !reloading) { [refreshHeaderView flipImageAnimated:YES]; [refreshHeaderView setStatus:kPullToReloadStatus]; [popSound play]; } else if (!refreshHeaderView.isFlipped && scrollView.contentOffset.y < -65.0f) { [refreshHeaderView flipImageAnimated:YES]; [refreshHeaderView setStatus:kReleaseToReloadStatus]; [psst1Sound play]; } } } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (reloading) return; if (scrollView.contentOffset.y <= - 65.0f) { if([self.tableView.dataSource respondsToSelector: @selector(reloadTableViewDataSource)]){ [self showReloadAnimationAnimated:YES]; [psst2Sound play]; [self reloadTableViewDataSource]; } } checkForRefresh = NO; } @end |
#import "PullToRefreshTableViewController.h" @interface AppDetailViewController : PullToRefreshTableViewController @end |
- (void)synchingDone:(NSNotification *)notification { refreshHeaderView.lastUpdatedDate = myApp.lastReviewRefresh; [super dataSourceDidFinishLoadingNewData]; } - (void)reloadTableViewDataSource { [myApp getAllReviews]; } |
if (alreadyReloading) [self showReloadAnimationAnimated:NO]; |