Skip to content

Commit

Permalink
Support scrollViews with a content inset
Browse files Browse the repository at this point in the history
  • Loading branch information
Sephiroth87 committed Aug 28, 2012
1 parent 25d4961 commit 27a5ba9
Show file tree
Hide file tree
Showing 2 changed files with 39 additions and 9 deletions.
2 changes: 2 additions & 0 deletions ODRefreshControl/ODRefreshControl.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
UIActivityIndicatorView *_activity;
BOOL _refreshing;
BOOL _canRefresh;
BOOL _ignoreInset;
BOOL _ignoreOffset;
}

@property (nonatomic, readonly) BOOL refreshing;
Expand Down
46 changes: 37 additions & 9 deletions ODRefreshControl/ODRefreshControl.m
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ @interface ODRefreshControl ()

@property (nonatomic, readwrite) BOOL refreshing;
@property (nonatomic, assign) UIScrollView *scrollView;
@property (nonatomic, assign) UIEdgeInsets originalContentInset;

@end

Expand All @@ -39,6 +40,7 @@ @implementation ODRefreshControl
@synthesize tintColor = _tintColor;

@synthesize scrollView = _scrollView;
@synthesize originalContentInset = _originalContentInset;

static inline CGFloat lerp(CGFloat a, CGFloat b, CGFloat p)
{
Expand All @@ -47,13 +49,16 @@ static inline CGFloat lerp(CGFloat a, CGFloat b, CGFloat p)

- (id)initInScrollView:(UIScrollView *)scrollView
{
self = [super initWithFrame:CGRectMake(0, -kTotalViewHeight, scrollView.frame.size.width, kTotalViewHeight)];
self = [super initWithFrame:CGRectMake(0, -(kTotalViewHeight + scrollView.contentInset.top), scrollView.frame.size.width, kTotalViewHeight)];

if (self) {
self.scrollView = scrollView;
self.originalContentInset = scrollView.contentInset;

self.autoresizingMask = UIViewAutoresizingFlexibleWidth;
[scrollView addSubview:self];
[scrollView addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:nil];
[scrollView addObserver:self forKeyPath:@"contentInset" options:NSKeyValueObservingOptionNew context:nil];

_activity = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
_activity.center = CGPointMake(floor(self.frame.size.width / 2), floor(self.frame.size.height / 2));
Expand All @@ -64,6 +69,8 @@ - (id)initInScrollView:(UIScrollView *)scrollView

_refreshing = NO;
_canRefresh = YES;
_ignoreInset = NO;
_ignoreOffset = NO;
_tintColor = [UIColor colorWithRed:155.0 / 255.0 green:162.0 / 255.0 blue:172.0 / 255.0 alpha:1.0];

_shapeLayer = [CAShapeLayer layer];
Expand Down Expand Up @@ -92,6 +99,7 @@ - (id)initInScrollView:(UIScrollView *)scrollView
- (void)dealloc
{
[self.scrollView removeObserver:self forKeyPath:@"contentOffset"];
[self.scrollView removeObserver:self forKeyPath:@"contentInset"];
self.scrollView = nil;
}

Expand All @@ -106,6 +114,7 @@ - (void)willMoveToSuperview:(UIView *)newSuperview
[super willMoveToSuperview:newSuperview];
if (!newSuperview) {
[self.scrollView removeObserver:self forKeyPath:@"contentOffset"];
[self.scrollView removeObserver:self forKeyPath:@"contentInset"];
self.scrollView = nil;
}
}
Expand All @@ -128,11 +137,19 @@ - (UIActivityIndicatorViewStyle)activityIndicatorViewStyle

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (!self.enabled) {
if ([keyPath isEqualToString:@"contentInset"]) {
if (!_ignoreInset) {
self.originalContentInset = [[change objectForKey:@"new"] UIEdgeInsetsValue];
self.frame = CGRectMake(0, -(kTotalViewHeight + self.scrollView.contentInset.top), self.scrollView.frame.size.width, kTotalViewHeight);
}
return;
}

if (!self.enabled || _ignoreOffset) {
return;
}

CGFloat offset = [[change objectForKey:@"new"] CGPointValue].y;
CGFloat offset = [[change objectForKey:@"new"] CGPointValue].y + self.originalContentInset.top;

if (_refreshing) {
if (offset != 0) {
Expand All @@ -142,12 +159,15 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
[CATransaction setValue:(id)kCFBooleanTrue forKey:kCATransactionDisableActions];
_shapeLayer.position = CGPointMake(0, kMaxDistance + offset + kOpenedViewHeight);
[CATransaction commit];
//_activity.center = CGPointMake(floor(self.frame.size.width / 2), MIN(offset + self.frame.size.height + floor(self.frame.size.height / 2), floor(self.frame.size.height / 2)));
_activity.center = CGPointMake(floor(self.frame.size.width / 2), MIN(offset + self.frame.size.height + floor(kOpenedViewHeight / 2), self.frame.size.height - kOpenedViewHeight/ 2));

// Set the inset only when bouncing back and not dragging
if (offset >= -kOpenedViewHeight && !self.scrollView.dragging) {
[self.scrollView setContentInset:UIEdgeInsetsMake(kOpenedViewHeight, 0, 0, 0)];
_ignoreInset = YES;
_ignoreOffset = YES;
[self.scrollView setContentInset:UIEdgeInsetsMake(kOpenedViewHeight + self.originalContentInset.top, self.originalContentInset.left, self.originalContentInset.bottom, self.originalContentInset.right)];
_ignoreInset = NO;
_ignoreOffset = NO;
}
}
return;
Expand Down Expand Up @@ -237,7 +257,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(N
[_arrowLayer setFillRule:kCAFillRuleEvenOdd];
CGPathRelease(arrowPath);

// Add thr highlight shape
// Add the highlight shape

CGMutablePathRef highlightPath = CGPathCreateMutable();
CGPathAddArc(highlightPath, NULL, topOrigin.x, topOrigin.y, currentTopRadius, 0, M_PI, YES);
Expand Down Expand Up @@ -318,7 +338,9 @@ - (void)beginRefreshing
_activity.layer.transform = CATransform3DMakeScale(1, 1, 1);

CGPoint offset = self.scrollView.contentOffset;
[self.scrollView setContentInset:UIEdgeInsetsMake(kOpenedViewHeight, 0, 0, 0)];
_ignoreInset = YES;
[self.scrollView setContentInset:UIEdgeInsetsMake(kOpenedViewHeight + self.originalContentInset.top, self.originalContentInset.left, self.originalContentInset.bottom, self.originalContentInset.right)];
_ignoreInset = NO;
[self.scrollView setContentOffset:offset animated:NO];

self.refreshing = YES;
Expand All @@ -336,7 +358,11 @@ - (void)endRefreshing
// in the case the scrollView is released while the animation is running
__block UIScrollView *blockScrollView = self.scrollView;
[UIView animateWithDuration:0.4 animations:^{
[blockScrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
_ignoreInset = YES;
[blockScrollView setContentInset:self.originalContentInset];
_ignoreInset = NO;
CGPoint offset = blockScrollView.contentOffset;
[blockScrollView setContentOffset:offset animated:NO];
_activity.alpha = 0;
_activity.layer.transform = CATransform3DMakeScale(0.1, 0.1, 1);
} completion:^(BOOL finished) {
Expand All @@ -350,7 +376,9 @@ - (void)endRefreshing
_highlightLayer.path = nil;
// We need to use the scrollView somehow in the end block,
// or it'll get released in the animation block.
[blockScrollView setContentInset:UIEdgeInsetsMake(0, 0, 0, 0)];
_ignoreInset = YES;
[blockScrollView setContentInset:self.originalContentInset];
_ignoreInset = NO;
}];
}
}
Expand Down

0 comments on commit 27a5ba9

Please sign in to comment.