Skip to content

Commit

Permalink
Add pull-to-refresh
Browse files Browse the repository at this point in the history
based on a somewhat-hacked version of @leah's pull-to-refresh: PullRefreshTableViewController
  • Loading branch information
cdzombak committed Feb 12, 2012
1 parent 8b12704 commit cda7782
Show file tree
Hide file tree
Showing 10 changed files with 279 additions and 2 deletions.
18 changes: 18 additions & 0 deletions CAENLabStatus.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,10 @@
93BBAB4814DCCBF800B19049 /* [email protected] in Resources */ = {isa = PBXBuildFile; fileRef = 93BBAB4214DCCBF800B19049 /* [email protected] */; };
93BBAB5B14DCF4BD00B19049 /* iTunesArtwork in Resources */ = {isa = PBXBuildFile; fileRef = 93BBAB5A14DCF4BD00B19049 /* iTunesArtwork */; };
93BBAB6B14E83AC000B19049 /* DZCSubLabsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93BBAB6A14E83AC000B19049 /* DZCSubLabsViewController.m */; };
93BBAB6E14E8491A00B19049 /* arrow.png in Resources */ = {isa = PBXBuildFile; fileRef = 93BBAB6D14E8491A00B19049 /* arrow.png */; };
93BBAB7114E8493300B19049 /* PullRefreshTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 93BBAB7014E8493300B19049 /* PullRefreshTableViewController.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; };
93BBAB7314E84A1700B19049 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93BBAB7214E84A1700B19049 /* QuartzCore.framework */; };
93BBAB7514E84D5400B19049 /* me_refresh.png in Resources */ = {isa = PBXBuildFile; fileRef = 93BBAB7414E84D5400B19049 /* me_refresh.png */; };
93D9F66414D3997600AD2152 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D9F66314D3997600AD2152 /* UIKit.framework */; };
93D9F66614D3997600AD2152 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D9F66514D3997600AD2152 /* Foundation.framework */; };
93D9F66814D3997600AD2152 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 93D9F66714D3997600AD2152 /* CoreGraphics.framework */; };
Expand Down Expand Up @@ -57,6 +61,11 @@
93BBAB5A14DCF4BD00B19049 /* iTunesArtwork */ = {isa = PBXFileReference; lastKnownFileType = file; path = iTunesArtwork; sourceTree = "<group>"; };
93BBAB6914E83AC000B19049 /* DZCSubLabsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DZCSubLabsViewController.h; sourceTree = "<group>"; };
93BBAB6A14E83AC000B19049 /* DZCSubLabsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = DZCSubLabsViewController.m; sourceTree = "<group>"; };
93BBAB6D14E8491A00B19049 /* arrow.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = arrow.png; sourceTree = "<group>"; };
93BBAB6F14E8493200B19049 /* PullRefreshTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PullRefreshTableViewController.h; sourceTree = "<group>"; };
93BBAB7014E8493300B19049 /* PullRefreshTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = PullRefreshTableViewController.m; sourceTree = "<group>"; };
93BBAB7214E84A1700B19049 /* QuartzCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; };
93BBAB7414E84D5400B19049 /* me_refresh.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = me_refresh.png; sourceTree = "<group>"; };
93D9F65F14D3997600AD2152 /* CAENLabStatus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = CAENLabStatus.app; sourceTree = BUILT_PRODUCTS_DIR; };
93D9F66314D3997600AD2152 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
93D9F66514D3997600AD2152 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
Expand Down Expand Up @@ -118,6 +127,7 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
93BBAB7314E84A1700B19049 /* QuartzCore.framework in Frameworks */,
93D9F66414D3997600AD2152 /* UIKit.framework in Frameworks */,
93D9F66614D3997600AD2152 /* Foundation.framework in Frameworks */,
93D9F66814D3997600AD2152 /* CoreGraphics.framework in Frameworks */,
Expand All @@ -130,6 +140,7 @@
93D9F65414D3997600AD2152 = {
isa = PBXGroup;
children = (
93BBAB7214E84A1700B19049 /* QuartzCore.framework */,
93D9F66914D3997600AD2152 /* CAENLabStatus */,
93D9F66214D3997600AD2152 /* Frameworks */,
93D9F66014D3997600AD2152 /* Products */,
Expand Down Expand Up @@ -183,6 +194,8 @@
93D9F68814D39C2B00AD2152 /* View Controllers */ = {
isa = PBXGroup;
children = (
93BBAB6F14E8493200B19049 /* PullRefreshTableViewController.h */,
93BBAB7014E8493300B19049 /* PullRefreshTableViewController.m */,
93E80C5914D797F5008850FE /* DZCAboutViewController.h */,
93E80C5A14D797F5008850FE /* DZCAboutViewController.m */,
93D9F68514D39C2500AD2152 /* DZCLabsViewController.h */,
Expand Down Expand Up @@ -279,6 +292,8 @@
93FDA8BF14D9FE1A00787F8C /* Resources */ = {
isa = PBXGroup;
children = (
93BBAB6D14E8491A00B19049 /* arrow.png */,
93BBAB7414E84D5400B19049 /* me_refresh.png */,
93BBAB5A14DCF4BD00B19049 /* iTunesArtwork */,
93BBAB3D14DCCBF800B19049 /* Icon-72.png */,
93BBAB3E14DCCBF800B19049 /* Icon-Small-50.png */,
Expand Down Expand Up @@ -356,6 +371,8 @@
93BBAB4714DCCBF800B19049 /* Icon.png in Resources */,
93BBAB4814DCCBF800B19049 /* [email protected] in Resources */,
93BBAB5B14DCF4BD00B19049 /* iTunesArtwork in Resources */,
93BBAB6E14E8491A00B19049 /* arrow.png in Resources */,
93BBAB7514E84D5400B19049 /* me_refresh.png in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down Expand Up @@ -388,6 +405,7 @@
93E80C5814D78812008850FE /* DZCLabStatusHelper.m in Sources */,
93E80C5C14D797F5008850FE /* DZCAboutViewController.m in Sources */,
93BBAB6B14E83AC000B19049 /* DZCSubLabsViewController.m in Sources */,
93BBAB7114E8493300B19049 /* PullRefreshTableViewController.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
Expand Down
4 changes: 3 additions & 1 deletion CAENLabStatus/DZCLabsViewController.h
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#import <UIKit/UIKit.h>

#import "PullRefreshTableViewController.h"

@class DZCDataController;

@interface DZCLabsViewController : UITableViewController
@interface DZCLabsViewController : PullRefreshTableViewController

@property(nonatomic, strong) DZCDataController *dataController;

Expand Down
4 changes: 4 additions & 0 deletions CAENLabStatus/DZCLabsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,12 @@ - (void)refreshData

- (void)loadData
{
[self startLoading];

[self.dataController labsAndStatusesWithBlock:^(NSDictionary *labsResult, NSError *error) {

[self stopLoading];

self.labsByStatus = nil;

if (error) {
Expand Down
3 changes: 2 additions & 1 deletion CAENLabStatus/DZCSubLabsViewController.h
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#import <UIKit/UIKit.h>
#import "PullRefreshTableViewController.h"

@class DZCLab;
@class DZCDataController;

@interface DZCSubLabsViewController : UITableViewController
@interface DZCSubLabsViewController : PullRefreshTableViewController

@property (nonatomic, readonly, strong) DZCLab *lab;
@property (nonatomic, strong) DZCDataController *dataController;
Expand Down
4 changes: 4 additions & 0 deletions CAENLabStatus/DZCSubLabsViewController.m
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ - (void)refreshData

- (void)loadData
{
[self startLoading];

self.labs = nil;

for (DZCLab *lab in self.lab.subLabs) {
Expand All @@ -84,6 +86,8 @@ - (void)loadData

[self.labs sortUsingSelector:@selector(compareHumanName:)];

[self stopLoading];

[self.tableView reloadData];
}

Expand Down
59 changes: 59 additions & 0 deletions CAENLabStatus/PullRefreshTableViewController.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
//
// PullRefreshTableViewController.h
// Plancast
//
// Created by Leah Culver on 7/2/10.
// Copyright (c) 2010 Leah Culver
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//

#import <UIKit/UIKit.h>


@interface PullRefreshTableViewController : UITableViewController {
UIView *refreshHeaderView;
UILabel *refreshLabel;
UIImageView *refreshArrow;
UIActivityIndicatorView *refreshSpinner;
BOOL isDragging;
BOOL isLoading;
NSString *textPull;
NSString *textRelease;
NSString *textLoading;
}

@property (nonatomic, retain) UIView *refreshHeaderView;
@property (nonatomic, retain) UILabel *refreshLabel;
@property (nonatomic, retain) UIImageView *refreshArrow;
@property (nonatomic, retain) UIActivityIndicatorView *refreshSpinner;
@property (nonatomic, copy) NSString *textPull;
@property (nonatomic, copy) NSString *textRelease;
@property (nonatomic, copy) NSString *textLoading;

- (void)setupStrings;
- (void)addPullToRefreshHeader;
- (void)startLoading;
- (void)stopLoading;
- (void)refreshData;

@end
189 changes: 189 additions & 0 deletions CAENLabStatus/PullRefreshTableViewController.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
//
// PullRefreshTableViewController.m
// Plancast
//
// Created by Leah Culver on 7/2/10.
// Copyright (c) 2010 Leah Culver
//
// Permission is hereby granted, free of charge, to any person
// obtaining a copy of this software and associated documentation
// files (the "Software"), to deal in the Software without
// restriction, including without limitation the rights to use,
// copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the
// Software is furnished to do so, subject to the following
// conditions:
//
// The above copyright notice and this permission notice shall be
// included in all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
// OTHER DEALINGS IN THE SOFTWARE.
//

#import <QuartzCore/QuartzCore.h>
#import "PullRefreshTableViewController.h"

#define REFRESH_HEADER_HEIGHT 52.0f


@implementation PullRefreshTableViewController

@synthesize textPull, textRelease, textLoading, refreshHeaderView, refreshLabel, refreshArrow, refreshSpinner;

- (id)initWithStyle:(UITableViewStyle)style {
self = [super initWithStyle:style];
if (self != nil) {
[self setupStrings];
}
return self;
}

- (id)initWithCoder:(NSCoder *)aDecoder {
self = [super initWithCoder:aDecoder];
if (self != nil) {
[self setupStrings];
}
return self;
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self != nil) {
[self setupStrings];
}
return self;
}

- (void)viewDidLoad {
[super viewDidLoad];
[self addPullToRefreshHeader];
}

- (void)setupStrings{
textPull = [[NSString alloc] initWithString:@"Pull to refresh..."];
textRelease = [[NSString alloc] initWithString:@"Release to refresh..."];
textLoading = [[NSString alloc] initWithString:@"Loading..."];
}

- (void)addPullToRefreshHeader {
refreshHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0, 0 - REFRESH_HEADER_HEIGHT, 320, REFRESH_HEADER_HEIGHT)];
refreshHeaderView.backgroundColor = [UIColor clearColor];

refreshLabel = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 320, REFRESH_HEADER_HEIGHT)];
refreshLabel.backgroundColor = [UIColor clearColor];
refreshLabel.font = [UIFont boldSystemFontOfSize:12.0];
refreshLabel.textAlignment = UITextAlignmentCenter;

refreshArrow = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"me_refresh.png"]];
refreshArrow.frame = CGRectMake(floorf((REFRESH_HEADER_HEIGHT - 42.5) / 2 + 10),
(floorf(REFRESH_HEADER_HEIGHT - 42.5) / 2),
42.5, 42.5);

refreshSpinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
refreshSpinner.frame = CGRectMake(floorf(floorf(REFRESH_HEADER_HEIGHT - 20) / 2), floorf((REFRESH_HEADER_HEIGHT - 20) / 2), 20, 20);
refreshSpinner.hidesWhenStopped = YES;

[refreshHeaderView addSubview:refreshLabel];
[refreshHeaderView addSubview:refreshArrow];
[refreshHeaderView addSubview:refreshSpinner];
[self.tableView addSubview:refreshHeaderView];
}

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
if (isLoading) return;
isDragging = YES;
}

- (void)scrollViewDidScroll:(UIScrollView *)scrollView {
if (isLoading) {
// Update the content inset, good for section headers
if (scrollView.contentOffset.y > 0)
self.tableView.contentInset = UIEdgeInsetsZero;
else if (scrollView.contentOffset.y >= -REFRESH_HEADER_HEIGHT)
self.tableView.contentInset = UIEdgeInsetsMake(-scrollView.contentOffset.y, 0, 0, 0);
} else if (isDragging && scrollView.contentOffset.y < 0) {
// Update the arrow direction and label
[UIView beginAnimations:nil context:NULL];
if (scrollView.contentOffset.y < -REFRESH_HEADER_HEIGHT) {
// User is scrolling above the header
refreshLabel.text = self.textRelease;
[refreshArrow layer].transform = CATransform3DMakeRotation(M_PI, 0, 0, 1);
} else { // User is scrolling somewhere within the header
refreshLabel.text = self.textPull;
[refreshArrow layer].transform = CATransform3DMakeRotation(M_PI * 2, 0, 0, 1);
}
[UIView commitAnimations];
}
}

- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
if (isLoading) return;
isDragging = NO;
if (scrollView.contentOffset.y <= -REFRESH_HEADER_HEIGHT) {
// Released above the header
[self startLoading];
[self refreshData];
}
}

- (void)startLoading {
isLoading = YES;

// Show the header
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.3];
self.tableView.contentInset = UIEdgeInsetsMake(REFRESH_HEADER_HEIGHT, 0, 0, 0);
refreshLabel.text = self.textLoading;
refreshArrow.hidden = YES;
[refreshSpinner startAnimating];
[UIView commitAnimations];
}

- (void)stopLoading {
isLoading = NO;

// Hide the header
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDelegate:self];
[UIView setAnimationDuration:0.3];
[UIView setAnimationDidStopSelector:@selector(stopLoadingComplete:finished:context:)];
self.tableView.contentInset = UIEdgeInsetsZero;
UIEdgeInsets tableContentInset = self.tableView.contentInset;
tableContentInset.top = 0.0;
self.tableView.contentInset = tableContentInset;
[refreshArrow layer].transform = CATransform3DMakeRotation(M_PI * 2, 0, 0, 1);
[UIView commitAnimations];
}

- (void)stopLoadingComplete:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
// Reset the header
refreshLabel.text = self.textPull;
refreshArrow.hidden = NO;
[refreshSpinner stopAnimating];
}

- (void)refreshData {
// This is just a demo. Override this method with your custom reload action.
// Don't forget to call stopLoading at the end.
[self performSelector:@selector(stopLoading) withObject:nil afterDelay:2.0];
}

- (void)dealloc {
[refreshHeaderView release];
[refreshLabel release];
[refreshArrow release];
[refreshSpinner release];
[textPull release];
[textRelease release];
[textLoading release];
[super dealloc];
}

@end
Binary file added CAENLabStatus/Resources/arrow.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added CAENLabStatus/Resources/me_refresh.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added image_res/me_refresh.pxm
Binary file not shown.

0 comments on commit cda7782

Please sign in to comment.