diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..bc56769 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +*.xcworkspace +xcuserdata +build diff --git a/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.h b/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.h index ea0642b..0878e84 100755 --- a/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.h +++ b/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.h @@ -25,12 +25,18 @@ // @class EGORefreshTableHeaderView; +@class EGORefreshTableFooterView; @interface RootViewController : UITableViewController { EGORefreshTableHeaderView *refreshHeaderView; + EGORefreshTableFooterView *refreshFooterView; // Reloading should really be your tableviews model class // Putting it here for demo purposes - BOOL _reloading; + BOOL _reloadingHeader; + BOOL _reloadingFooter; + + // Sample data - do not include in your project + NSMutableArray *_sampleData; } @property(assign,getter=isReloading) BOOL reloading; diff --git a/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.m b/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.m index 7ab3269..13ccbb6 100755 --- a/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.m +++ b/Demo/TableViewPull/Classes/Controller/RootViewController/RootViewController.m @@ -26,10 +26,14 @@ #import "RootViewController.h" #import "EGORefreshTableHeaderView.h" +#import "EGORefreshTableFooterView.h" @interface RootViewController (Private) - (void)dataSourceDidFinishLoadingNewData; +- (float)tableViewHeight; +- (void)repositionRefreshHeaderView; +- (float)endOfTableView:(UIScrollView *)scrollView; @end @@ -41,7 +45,9 @@ @implementation RootViewController - (void)viewDidLoad { [super viewDidLoad]; - + + _sampleData = [[NSMutableArray alloc] initWithObjects:@"1",@"2",@"3",@"4",@"5",@"6",@"7",@"8",@"9",@"10",nil]; + [self.tableView reloadData]; if (refreshHeaderView == nil) { refreshHeaderView = [[EGORefreshTableHeaderView alloc] initWithFrame:CGRectMake(0.0f, 0.0f - self.tableView.bounds.size.height, 320.0f, self.tableView.bounds.size.height)]; refreshHeaderView.backgroundColor = [UIColor colorWithRed:226.0/255.0 green:231.0/255.0 blue:237.0/255.0 alpha:1.0]; @@ -49,6 +55,14 @@ - (void)viewDidLoad { self.tableView.showsVerticalScrollIndicator = YES; [refreshHeaderView release]; } + + if (refreshFooterView == nil) { + refreshFooterView = [[EGORefreshTableFooterView alloc] initWithFrame:CGRectMake(0.0f, [self tableViewHeight], 320.0f, 600.0f)]; + refreshFooterView.backgroundColor = [UIColor colorWithRed:226.0/255.0 green:231.0/255.0 blue:237.0/255.0 alpha:1.0]; + [self.tableView addSubview:refreshFooterView]; + self.tableView.showsVerticalScrollIndicator = YES; + [refreshFooterView release]; + } } @@ -102,7 +116,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // Customize the number of rows in the table view. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return 0; + return _sampleData.count; } @@ -117,7 +131,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } // Configure the cell. - + cell.textLabel.text = [_sampleData objectAtIndex:indexPath.row]; return cell; } @@ -146,28 +160,23 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath */ -/* -// Override to support conditional editing of the table view. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - // Return NO if you do not want the specified item to be editable. return YES; } -*/ -/* -// Override to support editing the table view. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the row from the data source. + [_sampleData removeObjectAtIndex:indexPath.row]; [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; + [self repositionRefreshHeaderView]; } - else if (editingStyle == UITableViewCellEditingStyleInsert) { + //else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view. - } + //} } -*/ /* @@ -194,19 +203,36 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView{ } else if (refreshHeaderView.state == EGOOPullRefreshNormal && scrollView.contentOffset.y < -65.0f && !_reloading) { [refreshHeaderView setState:EGOOPullRefreshPulling]; } + + float endOfTable = [self endOfTableView:scrollView]; + if (refreshFooterView.state == EGOOPullRefreshPulling && endOfTable < 0.0f && endOfTable > -65.0f && !_reloading) { + [refreshFooterView setState:EGOOPullRefreshNormal]; + } else if (refreshFooterView.state == EGOOPullRefreshNormal && endOfTable < -65.0f && !_reloading) { + [refreshFooterView setState:EGOOPullRefreshPulling]; + } } } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate{ if (scrollView.contentOffset.y <= - 65.0f && !_reloading) { - _reloading = YES; - [self reloadTableViewDataSource]; - [refreshHeaderView setState:EGOOPullRefreshLoading]; - [UIView beginAnimations:nil context:NULL]; - [UIView setAnimationDuration:0.2]; - self.tableView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f); - [UIView commitAnimations]; + _reloading = YES; + [self reloadTableViewDataSource]; + [refreshHeaderView setState:EGOOPullRefreshLoading]; + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.2]; + self.tableView.contentInset = UIEdgeInsetsMake(60.0f, 0.0f, 0.0f, 0.0f); + [UIView commitAnimations]; + } + + if ([self endOfTableView:scrollView] <= -65.0f && !_reloading) { + _reloading = YES; + [self reloadTableViewDataSource]; + [refreshFooterView setState:EGOOPullRefreshLoading]; + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.2]; + self.tableView.contentInset = UIEdgeInsetsMake(0.0f, 0.0f, 60.0f, 0.0f); + [UIView commitAnimations]; } } @@ -219,8 +245,29 @@ - (void)dataSourceDidFinishLoadingNewData{ [self.tableView setContentInset:UIEdgeInsetsMake(0.0f, 0.0f, 0.0f, 0.0f)]; [UIView commitAnimations]; - [refreshHeaderView setState:EGOOPullRefreshNormal]; - [refreshHeaderView setCurrentDate]; // should check if data reload was successful + if ([refreshHeaderView state] != EGOOPullRefreshNormal) { + [refreshHeaderView setState:EGOOPullRefreshNormal]; + [refreshHeaderView setCurrentDate]; // should check if data reload was successful + } + + if ([refreshFooterView state] != EGOOPullRefreshNormal) { + [refreshFooterView setState:EGOOPullRefreshNormal]; + [refreshFooterView setCurrentDate]; // should check if data reload was successful + } +} + +- (float)tableViewHeight { + + // return height of table view + return [self.tableView contentSize].height; +} + +- (void)repositionRefreshHeaderView { + refreshFooterView.center = CGPointMake(160.0f, [self tableViewHeight] + 300.0f); +} + +- (float)endOfTableView:(UIScrollView *)scrollView { + return [self tableViewHeight] - scrollView.bounds.size.height - scrollView.bounds.origin.y; } #pragma mark - @@ -228,6 +275,7 @@ - (void)dataSourceDidFinishLoadingNewData{ - (void)dealloc { refreshHeaderView = nil; + [_sampleData release]; [super dealloc]; } diff --git a/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableFooterView.h b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableFooterView.h new file mode 100644 index 0000000..d38ec6a --- /dev/null +++ b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableFooterView.h @@ -0,0 +1,35 @@ +// +// EGORefreshTableFooterView.h +// Demo +// +// Created by Zbigniew Kominek on 3/10/11. +// Copyright 2011 Zbigniew Kominek. All rights reserved. +// +// 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 +#import "EGORefreshTableHeaderView.h" + + +@interface EGORefreshTableFooterView : EGORefreshTableHeaderView { + +} + +@end diff --git a/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableFooterView.m b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableFooterView.m new file mode 100644 index 0000000..77c1c78 --- /dev/null +++ b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableFooterView.m @@ -0,0 +1,48 @@ +// +// EGORefreshTableFooterView.m +// Demo +// +// Created by Zbigniew Kominek on 3/10/11. +// Copyright 2011 Zbigniew Kominek. All rights reserved. +// +// 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 "EGORefreshTableFooterView.h" + + +@implementation EGORefreshTableFooterView + +- (void)setup:(CGRect)frame { + _lastUpdatedLabelFrame = CGRectMake(0.0f, 10.0f, self.frame.size.width, 20.0f); + _statusLabelFrame = CGRectMake(0.0f, 28.0f, self.frame.size.width, 20.0f); + _arrowImageFrame = CGRectMake(25.0f, 10.0f, 30.0f, 55.0f); + _activityViewFrame = CGRectMake(25.0f, 18.0f, 20.0f, 20.0f); + + _arrowPullingTransform = CATransform3DMakeRotation((M_PI / 180.0f) * -360.0f, 0.0f, 0.0f, 1.0f); + _arrowNormalTransform = CATransform3DMakeRotation((M_PI / 180.0f) * 180.0f, 0.0f, 0.0f, 1.0f); + + _releaseLabelText = NSLocalizedString(@"Release to refresh...", @"Release to refresh status"); + _pullingLabelText = NSLocalizedString(@"Pull up to refresh...", @"Pull down to refresh status"); + _loadingLabelText = NSLocalizedString(@"Loading...", @"Loading Status"); + + _userDefaultsKey = @"EGORefreshTableFooterView_LastRefresh"; +} + +@end diff --git a/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.h b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.h index c092b65..36c0de7 100755 --- a/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.h +++ b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.h @@ -43,11 +43,29 @@ typedef enum{ EGOPullRefreshState _state; +@protected + CGRect _lastUpdatedLabelFrame; + CGRect _statusLabelFrame; + CGRect _arrowImageFrame; + CGRect _activityViewFrame; + + CATransform3D _arrowPullingTransform; + CATransform3D _arrowNormalTransform; + + NSString *_releaseLabelText; + NSString *_pullingLabelText; + NSString *_loadingLabelText; + + NSString *_userDefaultsKey; } @property(nonatomic,assign) EGOPullRefreshState state; +@property(nonatomic,retain) NSString *releaseLabelText; +@property(nonatomic,retain) NSString *pullingLabelText; +@property(nonatomic,retain) NSString *loadingLabelText; - (void)setCurrentDate; - (void)setState:(EGOPullRefreshState)aState; +- (void)setup:(CGRect)frame; @end diff --git a/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.m b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.m index 3c64e72..ff86f71 100755 --- a/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.m +++ b/Demo/TableViewPull/Classes/View/RefreshTableHeaderView/EGORefreshTableHeaderView.m @@ -34,14 +34,18 @@ @implementation EGORefreshTableHeaderView @synthesize state=_state; - +@synthesize releaseLabelText=_releaseLabelText; +@synthesize pullingLabelText=_pullingLabelText; +@synthesize loadingLabelText=_loadingLabelText; - (id)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { + if ((self = [super initWithFrame:frame])) { + [self setup:frame]; + self.autoresizingMask = UIViewAutoresizingFlexibleWidth; - UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 30.0f, self.frame.size.width, 20.0f)]; + UILabel *label = [[UILabel alloc] initWithFrame:_lastUpdatedLabelFrame]; label.autoresizingMask = UIViewAutoresizingFlexibleWidth; label.font = [UIFont systemFontOfSize:12.0f]; label.textColor = TEXT_COLOR; @@ -53,13 +57,13 @@ - (id)initWithFrame:(CGRect)frame { _lastUpdatedLabel=label; [label release]; - if ([[NSUserDefaults standardUserDefaults] objectForKey:@"EGORefreshTableView_LastRefresh"]) { - _lastUpdatedLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"EGORefreshTableView_LastRefresh"]; + if ([[NSUserDefaults standardUserDefaults] objectForKey:_userDefaultsKey]) { + _lastUpdatedLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:_userDefaultsKey]; } else { [self setCurrentDate]; } - label = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 48.0f, self.frame.size.width, 20.0f)]; + label = [[UILabel alloc] initWithFrame:_statusLabelFrame]; label.autoresizingMask = UIViewAutoresizingFlexibleWidth; label.font = [UIFont boldSystemFontOfSize:13.0f]; label.textColor = TEXT_COLOR; @@ -72,7 +76,7 @@ - (id)initWithFrame:(CGRect)frame { [label release]; CALayer *layer = [[CALayer alloc] init]; - layer.frame = CGRectMake(25.0f, frame.size.height - 65.0f, 30.0f, 55.0f); + layer.frame = _arrowImageFrame; layer.contentsGravity = kCAGravityResizeAspect; layer.contents = (id)[UIImage imageNamed:@"blueArrow.png"].CGImage; @@ -87,7 +91,7 @@ - (id)initWithFrame:(CGRect)frame { [layer release]; UIActivityIndicatorView *view = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - view.frame = CGRectMake(25.0f, frame.size.height - 38.0f, 20.0f, 20.0f); + view.frame = _activityViewFrame; [self addSubview:view]; _activityView = view; [view release]; @@ -102,9 +106,9 @@ - (void)setCurrentDate { NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setAMSymbol:@"AM"]; [formatter setPMSymbol:@"PM"]; - [formatter setDateFormat:@"MM/dd/yyyy hh:mm:a"]; + [formatter setDateFormat:@"MM/dd/yyyy hh:mm a"]; _lastUpdatedLabel.text = [NSString stringWithFormat:@"Last Updated: %@", [formatter stringFromDate:[NSDate date]]]; - [[NSUserDefaults standardUserDefaults] setObject:_lastUpdatedLabel.text forKey:@"EGORefreshTableView_LastRefresh"]; + [[NSUserDefaults standardUserDefaults] setObject:_lastUpdatedLabel.text forKey:_userDefaultsKey]; [[NSUserDefaults standardUserDefaults] synchronize]; [formatter release]; } @@ -114,10 +118,10 @@ - (void)setState:(EGOPullRefreshState)aState{ switch (aState) { case EGOOPullRefreshPulling: - _statusLabel.text = NSLocalizedString(@"Release to refresh...", @"Release to refresh status"); + _statusLabel.text = _releaseLabelText; [CATransaction begin]; [CATransaction setAnimationDuration:FLIP_ANIMATION_DURATION]; - _arrowImage.transform = CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.0f); + _arrowImage.transform = _arrowPullingTransform; [CATransaction commit]; break; @@ -130,18 +134,18 @@ - (void)setState:(EGOPullRefreshState)aState{ [CATransaction commit]; } - _statusLabel.text = NSLocalizedString(@"Pull down to refresh...", @"Pull down to refresh status"); + _statusLabel.text = _pullingLabelText; [_activityView stopAnimating]; [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; _arrowImage.hidden = NO; - _arrowImage.transform = CATransform3DIdentity; + _arrowImage.transform = _arrowNormalTransform; [CATransaction commit]; break; case EGOOPullRefreshLoading: - _statusLabel.text = NSLocalizedString(@"Loading...", @"Loading Status"); + _statusLabel.text = _loadingLabelText; [_activityView startAnimating]; [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; @@ -156,6 +160,22 @@ - (void)setState:(EGOPullRefreshState)aState{ _state = aState; } +- (void)setup:(CGRect)frame { + _lastUpdatedLabelFrame = CGRectMake(0.0f, frame.size.height - 30.0f, self.frame.size.width, 20.0f); + _statusLabelFrame = CGRectMake(0.0f, frame.size.height - 48.0f, self.frame.size.width, 20.0f); + _arrowImageFrame = CGRectMake(25.0f, frame.size.height - 65.0f, 30.0f, 55.0f); + _activityViewFrame = CGRectMake(25.0f, frame.size.height - 38.0f, 20.0f, 20.0f); + + _arrowPullingTransform = CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.0f); + _arrowNormalTransform = CATransform3DIdentity; + + _releaseLabelText = NSLocalizedString(@"Release to refresh...", @"Release to refresh status"); + _pullingLabelText = NSLocalizedString(@"Pull down to refresh...", @"Pull down to refresh status"); + _loadingLabelText = NSLocalizedString(@"Loading...", @"Loading Status"); + + _userDefaultsKey = @"EGORefreshTableHeaderView_LastRefresh"; +} + - (void)dealloc { _activityView = nil; _statusLabel = nil; diff --git a/Demo/TableViewPull/TableViewPull.xcodeproj/project.pbxproj b/Demo/TableViewPull/TableViewPull.xcodeproj/project.pbxproj index 38bbee4..6a4f91c 100755 --- a/Demo/TableViewPull/TableViewPull.xcodeproj/project.pbxproj +++ b/Demo/TableViewPull/TableViewPull.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 1D60589F0D05DD5A006BFB54 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1D30AB110D05D00D00671497 /* Foundation.framework */; }; 1DF5F4E00D08C38300B7A737 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */; }; + 267789F513296258002564C5 /* EGORefreshTableFooterView.m in Sources */ = {isa = PBXBuildFile; fileRef = 267789F413296258002564C5 /* EGORefreshTableFooterView.m */; }; 2892E4100DC94CBA00A64D0F /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */; }; 28AD73600D9D9599002E5188 /* MainWindow.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28AD735F0D9D9599002E5188 /* MainWindow.xib */; }; 28F335F11007B36200424DE2 /* RootViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 28F335F01007B36200424DE2 /* RootViewController.xib */; }; @@ -31,6 +32,8 @@ 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 1D6058910D05DD3D006BFB54 /* TableViewPull.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = TableViewPull.app; sourceTree = BUILT_PRODUCTS_DIR; }; 1DF5F4DF0D08C38300B7A737 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; + 267789F313296258002564C5 /* EGORefreshTableFooterView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = EGORefreshTableFooterView.h; sourceTree = ""; }; + 267789F413296258002564C5 /* EGORefreshTableFooterView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = EGORefreshTableFooterView.m; sourceTree = ""; }; 2892E40F0DC94CBA00A64D0F /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 28AD735F0D9D9599002E5188 /* MainWindow.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MainWindow.xib; sourceTree = ""; }; 28F335F01007B36200424DE2 /* RootViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = RootViewController.xib; sourceTree = ""; }; @@ -167,6 +170,8 @@ children = ( 3A3D909C11188064002B6585 /* EGORefreshTableHeaderView.h */, 3A3D909D11188064002B6585 /* EGORefreshTableHeaderView.m */, + 267789F313296258002564C5 /* EGORefreshTableFooterView.h */, + 267789F413296258002564C5 /* EGORefreshTableFooterView.m */, ); path = RefreshTableHeaderView; sourceTree = ""; @@ -254,6 +259,7 @@ 3A3D909E11188064002B6585 /* EGORefreshTableHeaderView.m in Sources */, 3A3D90A8111881DE002B6585 /* RootViewController.m in Sources */, 3A3D910311188495002B6585 /* main.m in Sources */, + 267789F513296258002564C5 /* EGORefreshTableFooterView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -272,6 +278,7 @@ INFOPLIST_FILE = "Resources/TableViewPull-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 3.0; PRODUCT_NAME = TableViewPull; + SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; @@ -286,6 +293,7 @@ INFOPLIST_FILE = "Resources/TableViewPull-Info.plist"; IPHONEOS_DEPLOYMENT_TARGET = 3.0; PRODUCT_NAME = TableViewPull; + SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Release; diff --git a/EGOTableViewPullRefresh/Classes/View/EGORefreshTableFooterView.h b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableFooterView.h new file mode 100644 index 0000000..d38ec6a --- /dev/null +++ b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableFooterView.h @@ -0,0 +1,35 @@ +// +// EGORefreshTableFooterView.h +// Demo +// +// Created by Zbigniew Kominek on 3/10/11. +// Copyright 2011 Zbigniew Kominek. All rights reserved. +// +// 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 +#import "EGORefreshTableHeaderView.h" + + +@interface EGORefreshTableFooterView : EGORefreshTableHeaderView { + +} + +@end diff --git a/EGOTableViewPullRefresh/Classes/View/EGORefreshTableFooterView.m b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableFooterView.m new file mode 100644 index 0000000..77c1c78 --- /dev/null +++ b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableFooterView.m @@ -0,0 +1,48 @@ +// +// EGORefreshTableFooterView.m +// Demo +// +// Created by Zbigniew Kominek on 3/10/11. +// Copyright 2011 Zbigniew Kominek. All rights reserved. +// +// 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 "EGORefreshTableFooterView.h" + + +@implementation EGORefreshTableFooterView + +- (void)setup:(CGRect)frame { + _lastUpdatedLabelFrame = CGRectMake(0.0f, 10.0f, self.frame.size.width, 20.0f); + _statusLabelFrame = CGRectMake(0.0f, 28.0f, self.frame.size.width, 20.0f); + _arrowImageFrame = CGRectMake(25.0f, 10.0f, 30.0f, 55.0f); + _activityViewFrame = CGRectMake(25.0f, 18.0f, 20.0f, 20.0f); + + _arrowPullingTransform = CATransform3DMakeRotation((M_PI / 180.0f) * -360.0f, 0.0f, 0.0f, 1.0f); + _arrowNormalTransform = CATransform3DMakeRotation((M_PI / 180.0f) * 180.0f, 0.0f, 0.0f, 1.0f); + + _releaseLabelText = NSLocalizedString(@"Release to refresh...", @"Release to refresh status"); + _pullingLabelText = NSLocalizedString(@"Pull up to refresh...", @"Pull down to refresh status"); + _loadingLabelText = NSLocalizedString(@"Loading...", @"Loading Status"); + + _userDefaultsKey = @"EGORefreshTableFooterView_LastRefresh"; +} + +@end diff --git a/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.h b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.h index cbfd952..36c0de7 100755 --- a/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.h +++ b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.h @@ -36,18 +36,36 @@ typedef enum{ @interface EGORefreshTableHeaderView : UIView { - UILabel *lastUpdatedLabel; - UILabel *statusLabel; - CALayer *arrowImage; - UIActivityIndicatorView *activityView; + UILabel *_lastUpdatedLabel; + UILabel *_statusLabel; + CALayer *_arrowImage; + UIActivityIndicatorView *_activityView; EGOPullRefreshState _state; +@protected + CGRect _lastUpdatedLabelFrame; + CGRect _statusLabelFrame; + CGRect _arrowImageFrame; + CGRect _activityViewFrame; + + CATransform3D _arrowPullingTransform; + CATransform3D _arrowNormalTransform; + + NSString *_releaseLabelText; + NSString *_pullingLabelText; + NSString *_loadingLabelText; + + NSString *_userDefaultsKey; } @property(nonatomic,assign) EGOPullRefreshState state; +@property(nonatomic,retain) NSString *releaseLabelText; +@property(nonatomic,retain) NSString *pullingLabelText; +@property(nonatomic,retain) NSString *loadingLabelText; - (void)setCurrentDate; - (void)setState:(EGOPullRefreshState)aState; +- (void)setup:(CGRect)frame; @end diff --git a/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.m b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.m index 9ac4970..ff86f71 100755 --- a/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.m +++ b/EGOTableViewPullRefresh/Classes/View/EGORefreshTableHeaderView.m @@ -29,81 +29,86 @@ #define TEXT_COLOR [UIColor colorWithRed:87.0/255.0 green:108.0/255.0 blue:137.0/255.0 alpha:1.0] #define BORDER_COLOR [UIColor colorWithRed:87.0/255.0 green:108.0/255.0 blue:137.0/255.0 alpha:1.0] - +#define FLIP_ANIMATION_DURATION 0.18f @implementation EGORefreshTableHeaderView @synthesize state=_state; - +@synthesize releaseLabelText=_releaseLabelText; +@synthesize pullingLabelText=_pullingLabelText; +@synthesize loadingLabelText=_loadingLabelText; - (id)initWithFrame:(CGRect)frame { - if (self = [super initWithFrame:frame]) { + if ((self = [super initWithFrame:frame])) { - self.autoresizingMask = UIViewAutoresizingFlexibleWidth; + [self setup:frame]; - lastUpdatedLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 30.0f, self.frame.size.width, 20.0f)]; - lastUpdatedLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; - 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 = [UIColor clearColor]; - lastUpdatedLabel.textAlignment = UITextAlignmentCenter; - [self addSubview:lastUpdatedLabel]; - [lastUpdatedLabel release]; + self.autoresizingMask = UIViewAutoresizingFlexibleWidth; + + UILabel *label = [[UILabel alloc] initWithFrame:_lastUpdatedLabelFrame]; + label.autoresizingMask = UIViewAutoresizingFlexibleWidth; + label.font = [UIFont systemFontOfSize:12.0f]; + label.textColor = TEXT_COLOR; + label.shadowColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; + label.shadowOffset = CGSizeMake(0.0f, 1.0f); + label.backgroundColor = [UIColor clearColor]; + label.textAlignment = UITextAlignmentCenter; + [self addSubview:label]; + _lastUpdatedLabel=label; + [label release]; - if ([[NSUserDefaults standardUserDefaults] objectForKey:@"EGORefreshTableView_LastRefresh"]) { - lastUpdatedLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:@"EGORefreshTableView_LastRefresh"]; + if ([[NSUserDefaults standardUserDefaults] objectForKey:_userDefaultsKey]) { + _lastUpdatedLabel.text = [[NSUserDefaults standardUserDefaults] objectForKey:_userDefaultsKey]; } else { [self setCurrentDate]; } - statusLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height - 48.0f, self.frame.size.width, 20.0f)]; - statusLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; - 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 = [UIColor clearColor]; - statusLabel.textAlignment = UITextAlignmentCenter; - [self setState:EGOOPullRefreshNormal]; - [self addSubview:statusLabel]; - [statusLabel release]; + label = [[UILabel alloc] initWithFrame:_statusLabelFrame]; + label.autoresizingMask = UIViewAutoresizingFlexibleWidth; + label.font = [UIFont boldSystemFontOfSize:13.0f]; + label.textColor = TEXT_COLOR; + label.shadowColor = [UIColor colorWithWhite:0.9f alpha:1.0f]; + label.shadowOffset = CGSizeMake(0.0f, 1.0f); + label.backgroundColor = [UIColor clearColor]; + label.textAlignment = UITextAlignmentCenter; + [self addSubview:label]; + _statusLabel=label; + [label release]; - arrowImage = [[CALayer alloc] init]; - arrowImage.frame = CGRectMake(25.0f, frame.size.height - 65.0f, 30.0f, 55.0f); - arrowImage.contentsGravity = kCAGravityResizeAspect; - arrowImage.contents = (id)[UIImage imageNamed:@"blueArrow.png"].CGImage; - [[self layer] addSublayer:arrowImage]; - [arrowImage release]; + CALayer *layer = [[CALayer alloc] init]; + layer.frame = _arrowImageFrame; + layer.contentsGravity = kCAGravityResizeAspect; + layer.contents = (id)[UIImage imageNamed:@"blueArrow.png"].CGImage; + +#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 + if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)]) { + layer.contentsScale = [[UIScreen mainScreen] scale]; + } +#endif - 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]; + [[self layer] addSublayer:layer]; + _arrowImage=layer; + [layer release]; + + UIActivityIndicatorView *view = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + view.frame = _activityViewFrame; + [self addSubview:view]; + _activityView = view; + [view release]; + + [self setState:EGOOPullRefreshNormal]; } 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)setCurrentDate { - NSDateFormatter* formatter = [[NSDateFormatter alloc] init]; + NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; [formatter setAMSymbol:@"AM"]; [formatter setPMSymbol:@"PM"]; - [formatter setDateFormat:@"MM/dd/yyyy hh:mm:a"]; - lastUpdatedLabel.text = [NSString stringWithFormat:@"Last Updated: %@", [formatter stringFromDate:[NSDate date]]]; - [[NSUserDefaults standardUserDefaults] setObject:lastUpdatedLabel.text forKey:@"EGORefreshTableView_LastRefresh"]; + [formatter setDateFormat:@"MM/dd/yyyy hh:mm a"]; + _lastUpdatedLabel.text = [NSString stringWithFormat:@"Last Updated: %@", [formatter stringFromDate:[NSDate date]]]; + [[NSUserDefaults standardUserDefaults] setObject:_lastUpdatedLabel.text forKey:_userDefaultsKey]; [[NSUserDefaults standardUserDefaults] synchronize]; [formatter release]; } @@ -113,10 +118,10 @@ - (void)setState:(EGOPullRefreshState)aState{ switch (aState) { case EGOOPullRefreshPulling: - statusLabel.text = @"Release to refresh..."; + _statusLabel.text = _releaseLabelText; [CATransaction begin]; - [CATransaction setAnimationDuration:.18]; - arrowImage.transform = CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.0f); + [CATransaction setAnimationDuration:FLIP_ANIMATION_DURATION]; + _arrowImage.transform = _arrowPullingTransform; [CATransaction commit]; break; @@ -124,27 +129,27 @@ - (void)setState:(EGOPullRefreshState)aState{ if (_state == EGOOPullRefreshPulling) { [CATransaction begin]; - [CATransaction setAnimationDuration:.18]; - arrowImage.transform = CATransform3DIdentity; + [CATransaction setAnimationDuration:FLIP_ANIMATION_DURATION]; + _arrowImage.transform = CATransform3DIdentity; [CATransaction commit]; } - statusLabel.text = @"Pull down to refresh..."; - [activityView stopAnimating]; + _statusLabel.text = _pullingLabelText; + [_activityView stopAnimating]; [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; - arrowImage.hidden = NO; - arrowImage.transform = CATransform3DIdentity; + _arrowImage.hidden = NO; + _arrowImage.transform = _arrowNormalTransform; [CATransaction commit]; break; case EGOOPullRefreshLoading: - statusLabel.text = @"Loading..."; - [activityView startAnimating]; + _statusLabel.text = _loadingLabelText; + [_activityView startAnimating]; [CATransaction begin]; [CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions]; - arrowImage.hidden = YES; + _arrowImage.hidden = YES; [CATransaction commit]; break; @@ -155,11 +160,27 @@ - (void)setState:(EGOPullRefreshState)aState{ _state = aState; } +- (void)setup:(CGRect)frame { + _lastUpdatedLabelFrame = CGRectMake(0.0f, frame.size.height - 30.0f, self.frame.size.width, 20.0f); + _statusLabelFrame = CGRectMake(0.0f, frame.size.height - 48.0f, self.frame.size.width, 20.0f); + _arrowImageFrame = CGRectMake(25.0f, frame.size.height - 65.0f, 30.0f, 55.0f); + _activityViewFrame = CGRectMake(25.0f, frame.size.height - 38.0f, 20.0f, 20.0f); + + _arrowPullingTransform = CATransform3DMakeRotation((M_PI / 180.0) * 180.0f, 0.0f, 0.0f, 1.0f); + _arrowNormalTransform = CATransform3DIdentity; + + _releaseLabelText = NSLocalizedString(@"Release to refresh...", @"Release to refresh status"); + _pullingLabelText = NSLocalizedString(@"Pull down to refresh...", @"Pull down to refresh status"); + _loadingLabelText = NSLocalizedString(@"Loading...", @"Loading Status"); + + _userDefaultsKey = @"EGORefreshTableHeaderView_LastRefresh"; +} + - (void)dealloc { - activityView = nil; - statusLabel = nil; - arrowImage = nil; - lastUpdatedLabel = nil; + _activityView = nil; + _statusLabel = nil; + _arrowImage = nil; + _lastUpdatedLabel = nil; [super dealloc]; }