diff --git a/TLYShyNavBar/TLYShyNavBarManager.m b/TLYShyNavBar/TLYShyNavBarManager.m index df58c53..14c0d69 100644 --- a/TLYShyNavBar/TLYShyNavBarManager.m +++ b/TLYShyNavBar/TLYShyNavBarManager.m @@ -22,6 +22,8 @@ static inline CGFloat AACStatusBarHeight() @interface TLYShyNavBarManager () @property (nonatomic, strong) TLYShyViewController *navBarController; +@property (nonatomic, strong) TLYShyViewController *extensionController; + @property (nonatomic, readwrite) UIView *extensionViewsContainer; @property (nonatomic) CGFloat previousYOffset; @@ -57,21 +59,22 @@ static inline CGFloat AACStatusBarHeight() self.extensionViewsContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100.f, 0.f)]; self.extensionViewsContainer.backgroundColor = [UIColor clearColor]; - TLYShyViewController *extensionController = [[TLYShyViewController alloc] init]; - extensionController.view = self.extensionViewsContainer; - extensionController.contractionAmount = ^(UIView *view) + self.extensionController = [[TLYShyViewController alloc] init]; + self.extensionController.view = self.extensionViewsContainer; + self.extensionController.hidesAfterContraction = YES; + self.extensionController.contractionAmount = ^(UIView *view) { return CGRectGetHeight(view.bounds); }; __weak typeof(self) weakSelf = self; - extensionController.expandedCenter = ^(UIView *view) + self.extensionController.expandedCenter = ^(UIView *view) { return CGPointMake(CGRectGetMidX(view.bounds), CGRectGetMidY(view.bounds) + weakSelf.viewController.topLayoutGuide.length); }; - self.navBarController.child = extensionController; + self.navBarController.child = self.extensionController; } return self; } @@ -148,11 +151,9 @@ static inline CGFloat AACStatusBarHeight() newContentOffset.y -= deltaY; [UIView animateWithDuration:fabs(deltaY/contractionVelocity) - delay:0 - options:UIViewAnimationOptionCurveLinear animations:^{ self.scrollView.contentOffset = newContentOffset; - } completion:nil]; + }]; } #pragma mark - public methods diff --git a/TLYShyNavBar/TLYShyViewController.h b/TLYShyNavBar/TLYShyViewController.h index 2298b0c..55142c0 100644 --- a/TLYShyNavBar/TLYShyViewController.h +++ b/TLYShyNavBar/TLYShyViewController.h @@ -19,22 +19,21 @@ typedef CGFloat(^TLYShyViewControllerContractionAmountBlock)(UIView *view); * triggered. We use this class to control the operations we perform on * the shy view. * - * ShyViewControllers can have a child, which gets the same offset - * updates as its parent. The use for this is to implement a drawer like - * functionality. When a parent is contracted/expanded, we want the child - * which is beneath the view to move the same amount so it remains hidden. + * We are making some dangerous assumtions here!!! Most importantly, + * the TLYShyViewController can only be a maximum depth of 2. Adding a + * child to an already childified node is not supported. */ @interface TLYShyViewController : NSObject -@property (nonatomic, strong) TLYShyViewController *child; - +@property (nonatomic, weak) TLYShyViewController *child; @property (nonatomic, weak) UIView *view; @property (nonatomic, copy) TLYShyViewControllerExpandedCenterBlock expandedCenter; @property (nonatomic, copy) TLYShyViewControllerContractionAmountBlock contractionAmount; @property (nonatomic) BOOL hidesSubviews; +@property (nonatomic) BOOL hidesAfterContraction; - (CGFloat)updateYOffset:(CGFloat)deltaY; diff --git a/TLYShyNavBar/TLYShyViewController.m b/TLYShyNavBar/TLYShyViewController.m index b9a05a8..90b2b0b 100644 --- a/TLYShyNavBar/TLYShyViewController.m +++ b/TLYShyNavBar/TLYShyViewController.m @@ -12,9 +12,6 @@ const CGFloat contractionVelocity = 40.f; @interface TLYShyViewController () -@property (nonatomic, weak) TLYShyViewController *parent; -@property (nonatomic, readonly) CGFloat parentYOffset; - @property (nonatomic) CGPoint expandedCenterValue; @property (nonatomic) CGFloat contractionAmountValue; @@ -24,13 +21,6 @@ const CGFloat contractionVelocity = 40.f; @implementation TLYShyViewController -- (void)setChild:(TLYShyViewController *)child -{ - _child.parent = nil; - _child = child; - _child.parent = self; -} - // convenience - (CGPoint)expandedCenterValue { @@ -47,47 +37,34 @@ const CGFloat contractionVelocity = 40.f; return CGPointMake(self.expandedCenterValue.x, self.expandedCenterValue.y - self.contractionAmountValue); } -- (CGFloat)parentYOffset -{ - CGFloat parentOffset = 0; - if (self.parent) - { - parentOffset = MIN(0, self.parent.view.center.y - self.parent.expandedCenterValue.y); - } - - return parentOffset; -} - +// This method is courtesy of GTScrollNavigationBar +// https://github.com/luugiathuy/GTScrollNavigationBar - (void)_updateSubviewsToAlpha:(CGFloat)alpha { for (UIView* view in self.view.subviews) { - NSString *className = NSStringFromClass([view class]); - if (![className isEqualToString:@"_UINavigationBarBackground"] && - ![className isEqualToString:@"_UINavigationBarBackIndicatorView"]) + bool isBackgroundView = view == self.view.subviews[0]; + bool isViewHidden = view.hidden || view.alpha < FLT_EPSILON; + + if (!isBackgroundView && !isViewHidden) { view.alpha = alpha; } } } -- (CGFloat)_updateYOffsetInternal:(CGFloat)deltaY +- (CGFloat)updateYOffset:(CGFloat)deltaY { - CGFloat newYOffset = self.view.center.y + deltaY - self.parentYOffset; + if (self.child && deltaY < 0) + { + deltaY = [self.child updateYOffset:deltaY]; + self.child.view.hidden = (deltaY) < 0; + } + + CGFloat newYOffset = self.view.center.y + deltaY; CGFloat newYCenter = MAX(MIN(self.expandedCenterValue.y, newYOffset), self.contractedCenterValue.y); - CGFloat residual = newYOffset - newYCenter; - - if (self.parent && deltaY < 0) - { - residual = [self.parent _updateYOffsetInternal:residual]; - } - else if (self.child && deltaY > 0) - { - residual = [self.child _updateYOffsetInternal:residual]; - } - - self.view.center = CGPointMake(self.expandedCenterValue.x, newYCenter + self.parentYOffset); + self.view.center = CGPointMake(self.expandedCenterValue.x, newYCenter); if (self.hidesSubviews) { @@ -97,52 +74,30 @@ const CGFloat contractionVelocity = 40.f; [self _updateSubviewsToAlpha:newAlpha]; } + CGFloat residual = newYOffset - newYCenter; + + if (self.child && deltaY > 0 && residual > 0) + { + residual = [self.child updateYOffset:residual]; + self.child.view.hidden = residual - (newYOffset - newYCenter) > 0; + } + return residual; } -- (CGFloat)updateYOffset:(CGFloat)deltaY -{ - if (self.child && deltaY < 0) - { - return [self.child updateYOffset:deltaY]; - } - else - { - return [self _updateYOffsetInternal:deltaY]; - } -} - - (CGFloat)snap:(BOOL)contract afterDelay:(NSTimeInterval)delay { CGFloat newYCenter = (contract ? self.expandedCenterValue.y - self.contractionAmountValue : self.expandedCenterValue.y); - CGFloat deltaY = newYCenter - (self.view.center.y - self.parentYOffset); + CGFloat deltaY = newYCenter - self.view.center.y; CGFloat duration = fabs(deltaY/contractionVelocity); - if (contract) - { - CGFloat childDelta = [self.child snap:contract afterDelay:delay]; - delay += fabs(childDelta/contractionVelocity); - - deltaY += childDelta; - } - else - { - deltaY += [self.child snap:contract afterDelay:delay+duration]; - } - - dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^ - { - NSLog(@"delay: %.4f", delay); - [UIView animateWithDuration:duration - delay:0 - options:UIViewAnimationOptionCurveLinear - animations:^{ - [self updateYOffset:deltaY]; - } completion:nil]; - }); + [UIView animateWithDuration:duration + animations:^{ + [self updateYOffset:deltaY]; + }]; return deltaY; } @@ -164,7 +119,6 @@ const CGFloat contractionVelocity = 40.f; { [self _updateSubviewsToAlpha:1.f]; } - [self.child cleanup]; }