From 3b8dfb9b8e6d983299ac8fbc7dc775eb7bc667f5 Mon Sep 17 00:00:00 2001 From: aceisScope Date: Fri, 19 Jul 2013 15:21:18 +0800 Subject: [PATCH 1/3] support loading-more by the end of scrollview --- .gitignore | 18 ++ .../project.pbxproj | 6 + .../SwipeViewExample/ViewController.m | 3 + SwipeView/SwipeView.h | 8 +- SwipeView/SwipeView.m | 79 ++++++- SwipeView/TailLoadingView.h | 41 ++++ SwipeView/TailLoadingView.m | 199 ++++++++++++++++++ 7 files changed, 352 insertions(+), 2 deletions(-) create mode 100644 .gitignore create mode 100644 SwipeView/TailLoadingView.h create mode 100644 SwipeView/TailLoadingView.m diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..89c499e --- /dev/null +++ b/.gitignore @@ -0,0 +1,18 @@ +# Xcode +.DS_Store +build/ +*.pbxuser +!default.pbxuser +*.mode1v3 +!default.mode1v3 +*.mode2v3 +!default.mode2v3 +*.perspectivev3 +!default.perspectivev3 +*.xcworkspace +!default.xcworkspace +xcuserdata +profile +*.moved-aside +DerivedData +.idea/ diff --git a/Examples/Basic Example/SwipeViewExample.xcodeproj/project.pbxproj b/Examples/Basic Example/SwipeViewExample.xcodeproj/project.pbxproj index 558e915..e032dd4 100644 --- a/Examples/Basic Example/SwipeViewExample.xcodeproj/project.pbxproj +++ b/Examples/Basic Example/SwipeViewExample.xcodeproj/project.pbxproj @@ -17,6 +17,7 @@ 01FA7D39145B5FCC00D118DB /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 01FA7D38145B5FCC00D118DB /* ViewController.m */; }; 01FA7D3C145B5FCC00D118DB /* ViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 01FA7D3A145B5FCC00D118DB /* ViewController.xib */; }; 01FACD23166114E800B8C1A0 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 01FACD22166114E800B8C1A0 /* Default-568h@2x.png */; }; + 047AA37617991BAC003D398E /* TailLoadingView.m in Sources */ = {isa = PBXBuildFile; fileRef = 047AA37517991BAC003D398E /* TailLoadingView.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ @@ -36,6 +37,8 @@ 01FA7D38145B5FCC00D118DB /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 01FA7D3B145B5FCC00D118DB /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = en.lproj/ViewController.xib; sourceTree = ""; }; 01FACD22166114E800B8C1A0 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = ""; }; + 047AA37417991BAC003D398E /* TailLoadingView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TailLoadingView.h; sourceTree = ""; }; + 047AA37517991BAC003D398E /* TailLoadingView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TailLoadingView.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -55,6 +58,8 @@ 019466D915B3129800B9CA30 /* SwipeView */ = { isa = PBXGroup; children = ( + 047AA37417991BAC003D398E /* TailLoadingView.h */, + 047AA37517991BAC003D398E /* TailLoadingView.m */, 019466DA15B3129800B9CA30 /* SwipeView.h */, 019466DB15B3129800B9CA30 /* SwipeView.m */, ); @@ -182,6 +187,7 @@ 01FA7D36145B5FCC00D118DB /* AppDelegate.m in Sources */, 01FA7D39145B5FCC00D118DB /* ViewController.m in Sources */, 019466DC15B3129800B9CA30 /* SwipeView.m in Sources */, + 047AA37617991BAC003D398E /* TailLoadingView.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/Examples/Basic Example/SwipeViewExample/ViewController.m b/Examples/Basic Example/SwipeViewExample/ViewController.m index aa90a83..c904ddd 100644 --- a/Examples/Basic Example/SwipeViewExample/ViewController.m +++ b/Examples/Basic Example/SwipeViewExample/ViewController.m @@ -54,6 +54,9 @@ - (void)viewDidLoad //configure page control _pageControl.numberOfPages = _swipeView.numberOfPages; _pageControl.defersCurrentPageDisplay = YES; + + //enable loading + [_swipeView enableLoadingView]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation diff --git a/SwipeView/SwipeView.h b/SwipeView/SwipeView.h index 75a79f5..e7517b6 100755 --- a/SwipeView/SwipeView.h +++ b/SwipeView/SwipeView.h @@ -41,7 +41,7 @@ #import - +#import "TailLoadingView.h" typedef enum { @@ -80,6 +80,10 @@ SwipeViewAlignment; @property (nonatomic, assign) BOOL defersItemViewLoading; @property (nonatomic, assign, getter = isVertical) BOOL vertical; +@property (nonatomic, readwrite) BOOL loadingViewEnabled; +@property (nonatomic, readonly) BOOL isLoading; +@property (nonatomic, strong) TailLoadingView *tailLoadingView; + - (void)reloadData; - (void)reloadItemAtIndex:(NSInteger)index; - (void)scrollByNumberOfItems:(NSInteger)itemCount duration:(NSTimeInterval)duration; @@ -89,6 +93,8 @@ SwipeViewAlignment; - (NSInteger)indexOfItemView:(UIView *)view; - (NSInteger)indexOfItemViewOrSubview:(UIView *)view; +- (void)enableLoadingView; + @end diff --git a/SwipeView/SwipeView.m b/SwipeView/SwipeView.m index 9da9808..2ee1a35 100755 --- a/SwipeView/SwipeView.m +++ b/SwipeView/SwipeView.m @@ -65,7 +65,7 @@ #import "SwipeView.h" -@interface SwipeView () +@interface SwipeView () @property (nonatomic, strong) UIScrollView *scrollView; @property (nonatomic, strong) NSMutableDictionary *itemViews; @@ -83,6 +83,8 @@ @interface SwipeView () @property (nonatomic, assign) CGFloat lastUpdateOffset; @property (nonatomic, strong) NSTimer *timer; +@property (nonatomic, readwrite) BOOL isLoading; + @end @@ -119,6 +121,8 @@ - (void)setUp _scrollView.scrollsToTop = NO; _scrollView.clipsToBounds = NO; + _loadingViewEnabled = NO; + _decelerationRate = _scrollView.decelerationRate; _itemViews = [[NSMutableDictionary alloc] init]; _previousItemIndex = 0; @@ -163,6 +167,7 @@ - (void)dealloc [_scrollView ah_release]; [_itemViews ah_release]; [_itemViewPool ah_release]; + [_tailLoadingView ah_release]; [super ah_dealloc]; } @@ -923,6 +928,38 @@ - (void)loadUnloadViews [self loadViewAtIndex:[number integerValue]]; } } + + //enable loading view + if (_loadingViewEnabled) + { + //remove loading view + if (([self currentPage] < [self numberOfPages] - 1) && _tailLoadingView) + { + [_tailLoadingView removeFromSuperview]; + } + + //add loading view + if ([self currentPage] == [self numberOfPages] - 1) + { + if (_tailLoadingView.superview == nil) { + + if (_tailLoadingView == nil) { + if (!_vertical) { + _tailLoadingView = [[TailLoadingView alloc] initWithFrame:CGRectMake(_scrollView.contentSize.width, 0, 80, _scrollView.bounds.size.height)]; + } + else{ + _tailLoadingView = [[TailLoadingView alloc] initWithFrame:CGRectMake(0, _scrollView.contentSize.height, _scrollView.bounds.size.width, 60)]; + [_tailLoadingView setIsVertical:_vertical]; + } + _tailLoadingView.delegate = self; + } + + [_scrollView addSubview:_tailLoadingView]; + [_scrollView bringSubviewToFront:_tailLoadingView]; + } + } + } + } } @@ -998,6 +1035,39 @@ - (void)didMoveToSuperview } } +#pragma mark - +#pragma mark - Tail Loading +- (void)enableLoadingView +{ + _loadingViewEnabled = YES; + _wrapEnabled = NO; +} + +- (void)startLoadMorePageContents +{ + //here should be some real data loading + _isLoading = YES; +} + +- (void)doneLoadingMorePageContents +{ + //real data loading done + _isLoading = NO; + [_tailLoadingView tailloadingScrollViewDataSourceDidFinishedLoading:_scrollView]; +} + +- (void)tailloadingDidTriggerLoad:(TailLoadingView *)view +{ + [self startLoadMorePageContents]; + [self performSelector:@selector(doneLoadingMorePageContents) withObject:nil afterDelay:3.0]; +} + +- (BOOL)tailloadDataSourceIsLoading:(TailLoadingView *)view +{ + return _isLoading; +} + + #pragma mark - #pragma mark Gestures and taps @@ -1093,6 +1163,9 @@ - (void)scrollViewDidScroll:(UIScrollView *)scrollView { _previousContentOffset = _scrollView.contentOffset; } + + if(_loadingViewEnabled) + [_tailLoadingView tailloadingScrollViewDidScroll:scrollView]; } - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView @@ -1119,6 +1192,10 @@ - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL { [_delegate swipeViewDidEndDragging:self willDecelerate:decelerate]; } + + if(_loadingViewEnabled) + [_tailLoadingView tailloadingScrollViewDidEndDragging:scrollView]; + } - (void)scrollViewWillBeginDecelerating:(UIScrollView *)scrollView diff --git a/SwipeView/TailLoadingView.h b/SwipeView/TailLoadingView.h new file mode 100644 index 0000000..38bcedf --- /dev/null +++ b/SwipeView/TailLoadingView.h @@ -0,0 +1,41 @@ +// +// TailLoadingView.h +// SwipeViewExample +// +// Created by B.H.Liu on 13-7-18. +// +// + +#import + + +typedef enum{ + TailLoadingDragging = 0, + TailLoadingOngoing, + TailLoadingNormal +} LoadingViewStatus; + +@class TailLoadingView; + +@protocol TailloadingDelegate + +- (void)tailloadingDidTriggerLoad:(TailLoadingView*)view; +- (BOOL)tailloadDataSourceIsLoading:(TailLoadingView*)view; + +@end + +@interface TailLoadingView : UIView +{ + UILabel *_loadingLabel; + UIActivityIndicatorView *_activityView; + LoadingViewStatus status; +} + +@property (nonatomic,assign) id delegate; +@property (nonatomic,readwrite) BOOL isVertical; + +- (void)tailloadingScrollViewDidScroll:(UIScrollView *)scrollView; +- (void)tailloadingScrollViewDidEndDragging:(UIScrollView *)scrollView; +- (void)tailloadingScrollViewDataSourceDidFinishedLoading:(UIScrollView *)scrollView; + +@end diff --git a/SwipeView/TailLoadingView.m b/SwipeView/TailLoadingView.m new file mode 100644 index 0000000..bd9ca8a --- /dev/null +++ b/SwipeView/TailLoadingView.m @@ -0,0 +1,199 @@ +// +// TailLoadingView.m +// SwipeViewExample +// +// Created by B.H.Liu on 13-7-18. +// +// + +#define RGB(r,g,b) [UIColor colorWithRed:r/255.0 green:g/255.0 blue:b/255.0 alpha:1.0] + +#import "TailLoadingView.h" + +@implementation TailLoadingView + +- (id)initWithFrame:(CGRect)frame +{ + self = [super initWithFrame:frame]; + if (self) { + // Initialization code + + self.backgroundColor = [UIColor clearColor]; + self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleTopMargin | UIViewAutoresizingFlexibleBottomMargin; + + _loadingLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, frame.size.height/2 + 20.0f, frame.size.width, 20.0f)]; + _loadingLabel.autoresizingMask = UIViewAutoresizingFlexibleWidth; + _loadingLabel.backgroundColor = [UIColor clearColor]; + _loadingLabel.font = [UIFont systemFontOfSize:10.0f]; + _loadingLabel.textColor = RGB(87, 108, 137); + _loadingLabel.textAlignment = NSTextAlignmentCenter; + [self addSubview:_loadingLabel]; + + _activityView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + _activityView.frame = CGRectMake(0.0f, 0.0f, 20.0f, 20.0f); + _activityView.center = CGPointMake(frame.size.width/2, frame.size.height/2); + [self addSubview:_activityView]; + + [self setIsVertical:NO]; + [self changeStatus:TailLoadingNormal]; + } + return self; +} + + +#pragma mark - +#pragma mark - private +- (void)changeStatus:(LoadingViewStatus)aStatus{ + + switch (aStatus) { + case TailLoadingDragging: + { + _loadingLabel.text = @"Release to load"; + } + + break; + case TailLoadingNormal: + { + _loadingLabel.text = @"Drag to load"; + [_activityView stopAnimating]; + } + + break; + case TailLoadingOngoing: + { + _loadingLabel.text = @"Loading..."; + [_activityView startAnimating]; + } + + break; + default: + break; + } + + status = aStatus; +} + +#pragma mark - +#pragma mark - ScrollView Methods + +- (void)tailloadingScrollViewDidScroll:(UIScrollView *)scrollView +{ + if (status == TailLoadingOngoing) + { + if (_isVertical) { + CGFloat offset = MAX((scrollView.contentSize.height - (scrollView.contentOffset.y + scrollView.frame.size.height))* -1, 0); + offset = MAX(offset, 60); + scrollView.contentInset = UIEdgeInsetsMake(0, 0.0f, offset, 0.0f); + scrollView.contentOffset = CGPointMake(0, scrollView.contentSize.height - scrollView.frame.size.height + 6); + }else{ + CGFloat offset = MAX((scrollView.contentSize.width - (scrollView.contentOffset.x + scrollView.frame.size.width))* -1, 0); + offset = MAX(offset, 60); + scrollView.contentInset = UIEdgeInsetsMake(0, 0.0f, 0.0f, offset); + scrollView.contentOffset = CGPointMake(scrollView.contentSize.width - scrollView.frame.size.width + 60, 0); + } + + } + else if (scrollView.isDragging) + { + + BOOL isloading = NO; + if ([_delegate respondsToSelector:@selector(tailloadDataSourceIsLoading:)]) { + isloading = [_delegate tailloadDataSourceIsLoading:self]; + } + + if (!_isVertical) { + if (status == TailLoadingDragging && scrollView.contentOffset.x + scrollView.frame.size.width < scrollView.contentSize.width+65.0f && scrollView.contentOffset.x > scrollView.contentSize.width && !isloading) + { + [self changeStatus:TailLoadingNormal]; + } + else if (status == TailLoadingNormal && scrollView.contentOffset.x + scrollView.frame.size.width > scrollView.contentSize.width+65.0f && !isloading) + { + [self changeStatus:TailLoadingDragging]; + } + }else{ + if (status == TailLoadingDragging && scrollView.contentOffset.y + scrollView.frame.size.height < scrollView.contentSize.height+65.0f && scrollView.contentOffset.y > scrollView.contentSize.height && !isloading) + { + [self changeStatus:TailLoadingNormal]; + } + else if (status == TailLoadingNormal && scrollView.contentOffset.y + scrollView.frame.size.height > scrollView.contentSize.height+65.0f && !isloading) + { + [self changeStatus:TailLoadingDragging]; + } + } + + + if (scrollView.contentInset.right != 0) { + scrollView.contentInset = UIEdgeInsetsZero; + } + + } + +} + +- (void)tailloadingScrollViewDidEndDragging:(UIScrollView *)scrollView { + + BOOL isloading = NO; + if ([_delegate respondsToSelector:@selector(tailloadDataSourceIsLoading:)]) + { + isloading = [_delegate tailloadDataSourceIsLoading:self]; + } + + if (!_isVertical) { + if (scrollView.contentOffset.x + scrollView.frame.size.width > scrollView.contentSize.width+65.0f && !isloading) { + + if ([_delegate respondsToSelector:@selector(tailloadingDidTriggerLoad:)]) + { + [_delegate tailloadingDidTriggerLoad:self]; + } + + [self changeStatus:TailLoadingOngoing]; + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.2]; + scrollView.contentInset = UIEdgeInsetsMake(0, 0.0f, 0.0f, 60.f); + scrollView.contentOffset = CGPointMake(scrollView.contentSize.width - scrollView.frame.size.width + 60, 0); + [UIView commitAnimations]; + + } + } + else{ + if (scrollView.contentOffset.y + scrollView.frame.size.height > scrollView.contentSize.height+55.0f && !isloading) { + + if ([_delegate respondsToSelector:@selector(tailloadingDidTriggerLoad:)]) + { + [_delegate tailloadingDidTriggerLoad:self]; + } + + [self changeStatus:TailLoadingOngoing]; + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:0.2]; + scrollView.contentInset = UIEdgeInsetsMake(0, 0.0f, 60.0f, 00.f); + scrollView.contentOffset = CGPointMake(0, scrollView.contentSize.height - scrollView.frame.size.height + 60); + [UIView commitAnimations]; + + } + } + +} + +- (void)tailloadingScrollViewDataSourceDidFinishedLoading:(UIScrollView *)scrollView +{ + [self changeStatus:TailLoadingNormal]; + [UIView beginAnimations:nil context:NULL]; + [UIView setAnimationDuration:.3]; + [scrollView setContentInset:UIEdgeInsetsZero]; + if (!_isVertical) { + if (scrollView.contentOffset.x >= scrollView.contentSize.width - scrollView.frame.size.width) { + scrollView.contentOffset = CGPointMake(scrollView.contentSize.width - scrollView.frame.size.width, 0); + } + }else{ + if (scrollView.contentOffset.y >= scrollView.contentSize.height - scrollView.frame.size.height) { + scrollView.contentOffset = CGPointMake(0, scrollView.contentSize.height - scrollView.frame.size.height); + } + } + + [UIView commitAnimations]; + +} + + +@end From 1892bbec0f170bafb298571364d035cad21bc2cf Mon Sep 17 00:00:00 2001 From: aceisScope Date: Fri, 19 Jul 2013 15:52:18 +0800 Subject: [PATCH 2/3] add delegate for loading action --- SwipeView/SwipeView.h | 3 +++ SwipeView/SwipeView.m | 3 +++ 2 files changed, 6 insertions(+) diff --git a/SwipeView/SwipeView.h b/SwipeView/SwipeView.h index e7517b6..8f0ea50 100755 --- a/SwipeView/SwipeView.h +++ b/SwipeView/SwipeView.h @@ -94,6 +94,7 @@ SwipeViewAlignment; - (NSInteger)indexOfItemViewOrSubview:(UIView *)view; - (void)enableLoadingView; +- (void)doneLoadingMorePageContents; @end @@ -120,4 +121,6 @@ SwipeViewAlignment; - (BOOL)swipeView:(SwipeView *)swipeView shouldSelectItemAtIndex:(NSInteger)index; - (void)swipeView:(SwipeView *)swipeView didSelectItemAtIndex:(NSInteger)index; +- (void)swipeViewLoadingMore:(SwipeView*)swipeView; + @end diff --git a/SwipeView/SwipeView.m b/SwipeView/SwipeView.m index 2ee1a35..47b2c07 100755 --- a/SwipeView/SwipeView.m +++ b/SwipeView/SwipeView.m @@ -1047,6 +1047,9 @@ - (void)startLoadMorePageContents { //here should be some real data loading _isLoading = YES; + if ([_delegate respondsToSelector:@selector(swipeViewLoadingMore:)]) { + [_delegate swipeViewLoadingMore:self]; + } } - (void)doneLoadingMorePageContents From b61b2a36848c761189fe447fda0109f387bf8a50 Mon Sep 17 00:00:00 2001 From: aceisScope Date: Mon, 22 Jul 2013 17:18:08 +0800 Subject: [PATCH 3/3] fix figure bug --- SwipeView/TailLoadingView.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/SwipeView/TailLoadingView.m b/SwipeView/TailLoadingView.m index bd9ca8a..cae091f 100644 --- a/SwipeView/TailLoadingView.m +++ b/SwipeView/TailLoadingView.m @@ -84,7 +84,7 @@ - (void)tailloadingScrollViewDidScroll:(UIScrollView *)scrollView CGFloat offset = MAX((scrollView.contentSize.height - (scrollView.contentOffset.y + scrollView.frame.size.height))* -1, 0); offset = MAX(offset, 60); scrollView.contentInset = UIEdgeInsetsMake(0, 0.0f, offset, 0.0f); - scrollView.contentOffset = CGPointMake(0, scrollView.contentSize.height - scrollView.frame.size.height + 6); + scrollView.contentOffset = CGPointMake(0, scrollView.contentSize.height - scrollView.frame.size.height + 60); }else{ CGFloat offset = MAX((scrollView.contentSize.width - (scrollView.contentOffset.x + scrollView.frame.size.width))* -1, 0); offset = MAX(offset, 60);