diff --git a/TLYShyNavBar/ShyControllers/TLYShyStatusBarController.m b/TLYShyNavBar/ShyControllers/TLYShyStatusBarController.m index 7729fc6..dc1b63e 100644 --- a/TLYShyNavBar/ShyControllers/TLYShyStatusBarController.m +++ b/TLYShyNavBar/ShyControllers/TLYShyStatusBarController.m @@ -20,7 +20,7 @@ static inline CGFloat AACStatusBarHeight(UIViewController *viewController) } // Modal views do not overlap the status bar, so no allowance need be made for it - if (viewController.presentingViewController != nil) + if (viewController.presentingViewController.presentedViewController == viewController) { return 0.f; } @@ -31,13 +31,6 @@ static inline CGFloat AACStatusBarHeight(UIViewController *viewController) UIView *view = viewController.view; CGRect frame = [view.superview convertRect:view.frame toView:view.window]; - BOOL viewOverlapsStatusBar = frame.origin.y < statusBarHeight; - - if (!viewOverlapsStatusBar) - { - return 0.f; - } - return statusBarHeight; } diff --git a/TLYShyNavBar/ShyControllers/TLYShyViewController.h b/TLYShyNavBar/ShyControllers/TLYShyViewController.h index 2c6a2fb..b7c8490 100644 --- a/TLYShyNavBar/ShyControllers/TLYShyViewController.h +++ b/TLYShyNavBar/ShyControllers/TLYShyViewController.h @@ -39,6 +39,13 @@ typedef CGFloat(^TLYShyViewControllerContractionAmountBlock)(UIView *view); @property (nonatomic) TLYShyNavBarFade fadeBehavior; +@property (nonatomic, readonly) BOOL contracted; +@property (nonatomic, readonly) BOOL expanded; + +/* Scale means the navbar's subviews will scale as the navbar contracts/expands. + */ +@property (nonatomic) BOOL scale; + /* Sticky means it will always stay in expanded state */ @property (nonatomic) BOOL sticky; diff --git a/TLYShyNavBar/ShyControllers/TLYShyViewController.m b/TLYShyNavBar/ShyControllers/TLYShyViewController.m index ad8e54d..75dcea4 100644 --- a/TLYShyNavBar/ShyControllers/TLYShyViewController.m +++ b/TLYShyNavBar/ShyControllers/TLYShyViewController.m @@ -22,11 +22,7 @@ - (CGFloat)maxYRelativeToView:(UIView *)superview - (CGFloat)calculateTotalHeightRecursively { - float overlap = [self.parent maxYRelativeToView:self.view]; - if ([self.parent isMemberOfClass:[TLYShyStatusBarController class]] && overlap - self.view.frame.origin.y > 0) { - overlap += overlap - self.view.frame.origin.y; - } - return CGRectGetHeight(self.view.bounds) - overlap + [self.parent calculateTotalHeightRecursively]; + return (self.expanded ? CGRectGetHeight(self.view.bounds) : 0) + [self.parent calculateTotalHeightRecursively]; } @end @@ -39,9 +35,6 @@ @interface TLYShyViewController () @property (nonatomic, assign) CGPoint contractedCenterValue; -@property (nonatomic, assign) BOOL contracted; -@property (nonatomic, assign) BOOL expanded; - @end @implementation TLYShyViewController @@ -81,6 +74,12 @@ - (BOOL)expanded #pragma mark - Private methods +- (void)_onProgressUpdate:(CGFloat)progress +{ + [self _onAlphaUpdate:progress]; + [self _onScaleUpdate:progress]; +} + - (void)_onAlphaUpdate:(CGFloat)alpha { if (self.sticky) @@ -125,6 +124,32 @@ - (void)_updateSubviewsAlpha:(CGFloat)alpha } } +- (void)_onScaleUpdate:(CGFloat)scale +{ + if (self.sticky) + { + [self _updateSubviewsScale:1.f]; + return; + } + + [self _updateSubviewsScale:self.scale ? scale : 1.f]; +} + +- (void)_updateSubviewsScale:(CGFloat)scale +{ + if (![self.view isKindOfClass:[UINavigationBar class]]) + { + return; + } + + UINavigationBar *navigationBar = (UINavigationBar *)self.view; + + for (UIView* view in navigationBar.topItem.titleView.subviews) + { + view.transform = scale < 1 ? CGAffineTransformMakeScale(scale, scale) : CGAffineTransformIdentity; + } +} + - (void)_updateCenter:(CGPoint)newCenter { CGPoint currentCenter = self.view.center; @@ -146,6 +171,16 @@ - (void)setFadeBehavior:(TLYShyNavBarFade)fadeBehavior } } +- (void)setScale:(BOOL)scale +{ + _scale = scale; + + if (!scale) + { + [self _onScaleUpdate:1.f]; + } +} + - (void)offsetCenterBy:(CGPoint)deltaPoint { self.view.center = CGPointMake(self.view.center.x + deltaPoint.x, @@ -173,7 +208,7 @@ - (CGFloat)updateYOffset:(CGFloat)deltaY CGFloat newAlpha = 1.f - (self.expandedCenterValue.y - self.view.center.y) / self.contractionAmountValue; newAlpha = MIN(MAX(FLT_EPSILON, newAlpha), 1.f); - [self _onAlphaUpdate:newAlpha]; + [self _onProgressUpdate:newAlpha]; residual = newYOffset - newYCenter; @@ -236,7 +271,7 @@ - (CGFloat)expand { self.view.hidden = NO; - [self _onAlphaUpdate:1.f]; + [self _onProgressUpdate:1.f]; CGFloat amountToMove = self.expandedCenterValue.y - self.view.center.y; @@ -250,7 +285,7 @@ - (CGFloat)contract { CGFloat amountToMove = self.contractedCenterValue.y - self.view.center.y; - [self _onAlphaUpdate:FLT_EPSILON]; + [self _onProgressUpdate:FLT_EPSILON]; [self _updateCenter:self.contractedCenterValue]; [self.subShyController contract]; diff --git a/TLYShyNavBar/TLYShyNavBarManager.h b/TLYShyNavBar/TLYShyNavBarManager.h index 0e507dc..c27d4ad 100644 --- a/TLYShyNavBar/TLYShyNavBarManager.h +++ b/TLYShyNavBar/TLYShyNavBarManager.h @@ -46,7 +46,7 @@ @property (nonatomic, readonly) CGRect extensionViewBounds; /* Make the navigation bar stick to the top without collapsing - * Deatuls to NO + * Defaults to NO */ @property (nonatomic) BOOL stickyNavigationBar; @@ -62,11 +62,20 @@ @property (nonatomic) CGFloat expansionResistance; // default 200 @property (nonatomic) CGFloat contractionResistance; // default 0 +/* Check the state of the control. + */ +@property (nonatomic, readonly) BOOL contracting; + /* Choose how the navbar fades as it contracts/expands. * Defaults to FadeSubviews */ @property (nonatomic) TLYShyNavBarFade fadeBehavior; +/* Choose if the navbar's subviews scale as the navbar contracts/expands. + * Defaults to NO + */ +@property (nonatomic) BOOL scale; + /* Use this to set if the controller have any kind of custom refresh control */ @property (nonatomic) BOOL hasCustomRefreshControl; @@ -91,9 +100,13 @@ @optional -- (void)shyNavBarManagerDidBecomeFullyContracted:(TLYShyNavBarManager *) shyNavBarManager; +- (void)shyNavBarManagerDidStartContracting:(TLYShyNavBarManager *) shyNavBarManager; - (void)shyNavBarManagerDidFinishContracting:(TLYShyNavBarManager *) shyNavBarManager; +- (void)shyNavBarManagerDidBecomeFullyContracted:(TLYShyNavBarManager *) shyNavBarManager; + +- (void)shyNavBarManagerDidStartExpanding:(TLYShyNavBarManager *) shyNavBarManager; - (void)shyNavBarManagerDidFinishExpanding:(TLYShyNavBarManager *) shyNavBarManager; +- (void)shyNavBarManagerDidBecomeFullyExpanded:(TLYShyNavBarManager *) shyNavBarManager; @end diff --git a/TLYShyNavBar/TLYShyNavBarManager.m b/TLYShyNavBar/TLYShyNavBarManager.m index 63f3267..daec607 100644 --- a/TLYShyNavBar/TLYShyNavBarManager.m +++ b/TLYShyNavBar/TLYShyNavBarManager.m @@ -39,10 +39,16 @@ @interface TLYShyNavBarManager () @property (nonatomic, assign) CGFloat previousYOffset; @property (nonatomic, assign) CGFloat resistanceConsumed; +@property (nonatomic, assign) BOOL startedContracting; +@property (nonatomic, assign) BOOL startedExpanding; +@property (nonatomic, assign) BOOL fullyContracted; +@property (nonatomic, assign) BOOL fullyExpanded; + @property (nonatomic, assign) BOOL contracting; @property (nonatomic, assign) BOOL previousContractionState; @property (nonatomic, readonly) BOOL isViewControllerVisible; +@property (nonatomic, readonly) BOOL isPageViewController; @end @@ -58,6 +64,10 @@ - (instancetype)init self.delegateProxy = [[TLYDelegateProxy alloc] initWithMiddleMan:self]; /* Initialize defaults */ + self.startedContracting = NO; + self.startedExpanding = NO; + self.fullyContracted = NO; + self.fullyExpanded = YES; self.contracting = NO; self.previousContractionState = YES; @@ -65,6 +75,7 @@ - (instancetype)init self.contractionResistance = 0.f; self.fadeBehavior = TLYShyNavBarFadeSubviews; + self.scale = NO; self.previousYOffset = NAN; /* Initialize shy controllers */ @@ -80,7 +91,7 @@ - (instancetype)init self.extensionController.view = self.extensionViewContainer; /* hierarchy setup */ - /* StatusBar <-- navbar <-->> extension <--> scrollView + /* StatusBar <--> navbar <--> extension <--> scrollView */ self.navBarController.parent = self.statusBarController; self.navBarController.child = self.extensionController; @@ -167,10 +178,19 @@ - (void)setScrollView:(UIScrollView *)scrollView self.delegateProxy.originalDelegate = _scrollView.delegate; _scrollView.delegate = (id)self.delegateProxy; } - - [self cleanup]; - [self layoutViews]; - + + if (self.isPageViewController) + { + UIEdgeInsets insets = UIEdgeInsetsMake(self.extensionController.calculateTotalHeightRecursively, + self.scrollView.contentInset.left, + self.scrollView.contentInset.bottom, + self.scrollView.contentInset.right); + + [self.scrollView tly_setInsets:insets]; + } + + self.previousYOffset = NAN; + [_scrollView addObserver:self forKeyPath:@"contentSize" options:0 context:kTLYShyNavBarManagerKVOContext]; } @@ -184,6 +204,11 @@ - (BOOL)isViewControllerVisible return self.viewController.isViewLoaded && self.viewController.view.window; } +- (BOOL)isPageViewController +{ + return [self.viewController isKindOfClass:[UIPageViewController class]]; +} + - (void)setDisable:(BOOL)disable { if (disable == _disable) @@ -230,6 +255,66 @@ - (void)setStickyExtensionView:(BOOL)stickyExtensionView self.extensionController.sticky = stickyExtensionView; } +- (void)setStartedContracting:(BOOL)startedContracting +{ + if (_startedContracting == startedContracting) + { + return; + } + + _startedContracting = startedContracting; + + if (startedContracting && [self.delegate respondsToSelector:@selector(shyNavBarManagerDidStartContracting:)]) + { + [self.delegate shyNavBarManagerDidStartContracting:self]; + } +} + +- (void)setStartedExpanding:(BOOL)startedExpanding +{ + if (_startedExpanding == startedExpanding) + { + return; + } + + _startedExpanding = startedExpanding; + + if (startedExpanding && [self.delegate respondsToSelector:@selector(shyNavBarManagerDidStartExpanding:)]) + { + [self.delegate shyNavBarManagerDidStartExpanding:self]; + } +} + +- (void)setFullyContracted:(BOOL)fullyContracted +{ + if (_fullyContracted == fullyContracted) + { + return; + } + + _fullyContracted = fullyContracted; + + if (fullyContracted && [self.delegate respondsToSelector:@selector(shyNavBarManagerDidBecomeFullyContracted:)]) + { + [self.delegate shyNavBarManagerDidBecomeFullyContracted:self]; + } +} + +- (void)setFullyExpanded:(BOOL)fullyExpanded +{ + if (_fullyExpanded == fullyExpanded) + { + return; + } + + _fullyExpanded = fullyExpanded; + + if (fullyExpanded && [self.delegate respondsToSelector:@selector(shyNavBarManagerDidBecomeFullyExpanded:)]) + { + [self.delegate shyNavBarManagerDidBecomeFullyExpanded:self]; + } +} + #pragma mark - Private methods @@ -312,6 +397,7 @@ - (void)_handleScrolling // 6 - Update the navigation bar shyViewController self.navBarController.fadeBehavior = self.fadeBehavior; + self.navBarController.scale = self.scale; // 7 - Inform the delegate if needed CGFloat maxNavY = CGRectGetMaxY(self.navBarController.view.frame); @@ -322,11 +408,11 @@ - (void)_handleScrolling } else { visibleTop = MAX(maxNavY, maxExtensionY); } - if (visibleTop == self.statusBarController.calculateTotalHeightRecursively) { - if ([self.delegate respondsToSelector:@selector(shyNavBarManagerDidBecomeFullyContracted:)]) { - [self.delegate shyNavBarManagerDidBecomeFullyContracted:self]; - } - } + + self.startedContracting = deltaY < 0; + self.startedExpanding = deltaY > 0; + self.fullyContracted = visibleTop == self.statusBarController.calculateTotalHeightRecursively; + self.fullyExpanded = visibleTop == self.extensionController.calculateTotalHeightRecursively; [self.navBarController updateYOffset:deltaY]; } @@ -371,7 +457,7 @@ - (void)observeValueForKeyPath:(NSString *)keyPath { if (context == kTLYShyNavBarManagerKVOContext) { - if (self.isViewControllerVisible && ![self _scrollViewIsSuffecientlyLong]) + if (!self.isPageViewController && self.isViewControllerVisible && ![self _scrollViewIsSuffecientlyLong]) { [self.navBarController expand]; } @@ -409,11 +495,6 @@ - (void)setExtensionView:(UIView *)view } } -- (void)prepareForDisplay -{ - [self cleanup]; -} - - (void)layoutViews { if (fabs([self.scrollViewController updateLayoutIfNeeded]) > FLT_EPSILON) @@ -493,13 +574,17 @@ + (void)load - (void)tly_swizzledViewWillAppear:(BOOL)animated { - [[self _internalShyNavBarManager] prepareForDisplay]; + [[self _internalShyNavBarManager] cleanup]; [self tly_swizzledViewWillAppear:animated]; } - (void)tly_swizzledViewDidLayoutSubviews { - [[self _internalShyNavBarManager] layoutViews]; + if (![self _internalShyNavBarManager].isPageViewController) + { + [[self _internalShyNavBarManager] layoutViews]; + } + [self tly_swizzledViewDidLayoutSubviews]; }