Modular offset calculation

added sticky navigation feature
added more tests

BRIEF:
Completely overhauled the offset implementation. Now, a "shyView" calculates it's position based on its parent maxY property. For the navigation bar, that would be the status bar. For the extension view, it would be the navigation bar.
This commit is contained in:
Mazyad Alabduljaleel 2015-10-10 14:04:59 -07:00
parent 0617cd18d4
commit 93402b62af
10 changed files with 316 additions and 82 deletions

View File

@ -53,6 +53,10 @@ This component helps you mimick the navigation bar auto scrolling that you see i
![](resources/ShyNavBar-7.gif)
+ Sticky navigation bar (Thanks [@TiagoVeloso](https://github.com/TiagoVeloso) !)
![](resources/ShyNavBar-9.gif)
+ Fade the entire navbar (Thanks [__@longsview__](https://github.com/longsview) !)
![](resources/ShyNavBar-8.gif)

View File

@ -52,7 +52,14 @@ typedef NS_ENUM(NSInteger, TLYShyNavBarFade) {
*/
@property (nonatomic, readonly) CGRect extensionViewBounds;
/* Sticky extension view
/* Make the navigation bar stick to the top without collapsing
* Deatuls to NO
*/
@property (nonatomic) BOOL stickyNavigationBar;
/* Make the extension view stick to the bottom of the navbar without
* collapsing
* Defaults to NO
*/
@property (nonatomic) BOOL stickyExtensionView;

View File

@ -33,8 +33,11 @@ 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) {
if (!viewOverlapsStatusBar)
{
return 0.f;
}
@ -60,10 +63,38 @@ static void * const kTLYShyNavBarManagerKVOContext = (void*)&kTLYShyNavBarManage
@end
@interface TLYShyStatusBarController : NSObject <TLYShyViewControllerParent>
@property (nonatomic, weak) UIViewController *viewController;
@end
@implementation TLYShyStatusBarController
- (CGFloat)viewMaxY
{
CGFloat statusBarHeight = AACStatusBarHeight(self.viewController);
/* The standard status bar is 20 pixels. The navigation bar extends 20 pixels up so it is overlapped by the status bar.
* When there is a larger than 20 pixel status bar (e.g. a phone call is in progress or GPS is active), the center needs
* to shift up 20 pixels to avoid this 'dead space' being visible above the usual nav bar.
*/
if (statusBarHeight > 20)
{
statusBarHeight -= 20;
}
return statusBarHeight;
}
@end
#pragma mark - TLYShyNavBarManager class
@interface TLYShyNavBarManager () <UIScrollViewDelegate>
@property (nonatomic, strong) id<TLYShyViewControllerParent> statusBarController;
@property (nonatomic, strong) TLYShyViewController *navBarController;
@property (nonatomic, strong) TLYShyViewController *extensionController;
@ -104,28 +135,10 @@ static void * const kTLYShyNavBarManagerKVOContext = (void*)&kTLYShyNavBarManage
self.previousScrollInsets = UIEdgeInsetsZero;
self.previousYOffset = NAN;
self.navBarController = [[TLYShyViewController alloc] init];
__weak __typeof(self) weakSelf = self;
self.navBarController.expandedCenter = ^(UIView *view)
{
CGFloat statusBarHeight = AACStatusBarHeight(weakSelf.viewController);
/* The standard status bar is 20 pixels. The navigation bar extends 20 pixels up so it is overlapped by the status bar.
* When there is a larger than 20 pixel status bar (e.g. a phone call is in progress or GPS is active), the center needs
* to shift up 20 pixels to avoid this 'dead space' being visible above the usual nav bar.
*/
if (statusBarHeight > 20)
statusBarHeight -= 20;
return CGPointMake(CGRectGetMidX(view.bounds),
CGRectGetMidY(view.bounds) + statusBarHeight);
};
self.statusBarController = [[TLYShyStatusBarController alloc] init];
self.navBarController.contractionAmount = ^(UIView *view)
{
return CGRectGetHeight(view.bounds);
};
self.navBarController = [[TLYShyViewController alloc] init];
self.navBarController.parent = self.statusBarController;
self.extensionViewContainer = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100.f, 0.f)];
self.extensionViewContainer.backgroundColor = [UIColor clearColor];
@ -133,17 +146,8 @@ static void * const kTLYShyNavBarManagerKVOContext = (void*)&kTLYShyNavBarManage
self.extensionController = [[TLYShyViewController alloc] init];
self.extensionController.view = self.extensionViewContainer;
self.extensionController.contractionAmount = ^(UIView *view)
{
return CGRectGetHeight(view.bounds);
};
self.extensionController.expandedCenter = ^(UIView *view)
{
return CGPointMake(CGRectGetMidX(view.bounds),
CGRectGetMidY(view.bounds) + weakSelf.viewController.tly_topLayoutGuide.length);
};
self.extensionController.parent = self.navBarController;
self.navBarController.child = self.extensionController;
[[NSNotificationCenter defaultCenter] addObserver:self
@ -234,13 +238,24 @@ static void * const kTLYShyNavBarManagerKVOContext = (void*)&kTLYShyNavBarManage
}
}
- (BOOL)stickyNavigationBar
{
return self.navBarController.sticky;
}
- (void)setStickyNavigationBar:(BOOL)stickyNavigationBar
{
self.navBarController.sticky = stickyNavigationBar;
}
- (BOOL)stickyExtensionView
{
return self.extensionController.sticky;
}
- (void)setStickyExtensionView:(BOOL)stickyExtensionView
{
_stickyExtensionView = stickyExtensionView;
if (self.navBarController) {
self.navBarController.stickyExtensionView = _stickyExtensionView;
}
self.extensionController.sticky = stickyExtensionView;
}
@ -320,6 +335,7 @@ static void * const kTLYShyNavBarManagerKVOContext = (void*)&kTLYShyNavBarManage
// 6 - Update the navigation bar shyViewController
self.navBarController.fadeBehavior = (TLYShyNavViewControllerFade)self.fadeBehavior;
[self.navBarController updateYOffset:deltaY];
}
@ -401,7 +417,7 @@ static void * const kTLYShyNavBarManagerKVOContext = (void*)&kTLYShyNavBarManage
- (void)layoutViews
{
UIEdgeInsets scrollInsets = self.scrollView.contentInset;
scrollInsets.top = CGRectGetHeight(self.extensionViewContainer.bounds) + self.viewController.tly_topLayoutGuide.length;
scrollInsets.top = self.extensionController.viewMaxY;
if (UIEdgeInsetsEqualToEdgeInsets(scrollInsets, self.previousScrollInsets))
{

View File

@ -25,6 +25,12 @@ typedef NS_ENUM(NSInteger, TLYShyNavViewControllerFade) {
TLYShyNavViewControllerFadeNavbar,
};
@protocol TLYShyViewControllerParent <NSObject>
@property (nonatomic, readonly) CGFloat viewMaxY;
@end
/* CLASS DESCRIPTION:
* ==================
* A shy view is a view that contracts when a scrolling event is
@ -39,20 +45,19 @@ typedef NS_ENUM(NSInteger, TLYShyNavViewControllerFade) {
@interface TLYShyViewController : NSObject
@property (nonatomic, weak) TLYShyViewController *child;
@property (nonatomic, weak) id<TLYShyViewControllerParent> parent;
@property (nonatomic, weak) UIView *view;
@property (nonatomic, copy) TLYShyViewControllerExpandedCenterBlock expandedCenter;
@property (nonatomic, copy) TLYShyViewControllerContractionAmountBlock contractionAmount;
@property (nonatomic) TLYShyNavViewControllerFade fadeBehavior;
@property (nonatomic, readonly) CGFloat totalHeight;
/* Sticky extension view
/* Sticky means it will always stay in expanded state
*/
@property (nonatomic) BOOL stickyExtensionView;
@property (nonatomic) BOOL sticky;
- (CGFloat)updateYOffset:(CGFloat)deltaY;
- (void)offsetCenterBy:(CGPoint)deltaPoint;
- (CGFloat)snap:(BOOL)contract;
@ -60,3 +65,7 @@ typedef NS_ENUM(NSInteger, TLYShyNavViewControllerFade) {
- (CGFloat)contract;
@end
@interface TLYShyViewController (AsParent) <TLYShyViewControllerParent>
@end

View File

@ -8,7 +8,16 @@
#import "TLYShyViewController.h"
const CGFloat contractionVelocity = 300.f;
@implementation TLYShyViewController (AsParent)
- (CGFloat)viewMaxY
{
return CGRectGetMaxY(self.view.frame);
}
@end
@interface TLYShyViewController ()
@ -29,12 +38,17 @@ const CGFloat contractionVelocity = 300.f;
// convenience
- (CGPoint)expandedCenterValue
{
return self.expandedCenter(self.view);
CGPoint center = CGPointMake(CGRectGetMidX(self.view.bounds),
CGRectGetMidY(self.view.bounds));
center.y += self.parent.viewMaxY;
return center;
}
- (CGFloat)contractionAmountValue
{
return self.contractionAmount(self.view);
return self.sticky ? 0.f : CGRectGetHeight(self.view.bounds);
}
- (CGPoint)contractedCenterValue
@ -61,6 +75,13 @@ const CGFloat contractionVelocity = 300.f;
- (void)_onAlphaUpdate:(CGFloat)alpha
{
if (self.sticky)
{
self.view.alpha = 1.f;
[self _updateSubviewsAlpha:1.f];
return;
}
switch (self.fadeBehavior) {
case TLYShyNavViewControllerFadeDisabled:
@ -96,6 +117,15 @@ const CGFloat contractionVelocity = 300.f;
}
}
- (void)_updateCenter:(CGPoint)newCenter
{
CGPoint currentCenter = self.view.center;
CGPoint deltaPoint = CGPointMake(newCenter.x - currentCenter.x,
newCenter.y - currentCenter.y);
[self offsetCenterBy:deltaPoint];
}
#pragma mark - Public methods
- (void)setFadeBehavior:(TLYShyNavViewControllerFade)fadeBehavior
@ -108,26 +138,26 @@ const CGFloat contractionVelocity = 300.f;
}
}
- (CGFloat)updateYOffset:(CGFloat)deltaY
- (void)offsetCenterBy:(CGPoint)deltaPoint
{
if (self.child && deltaY < 0 && !self.stickyExtensionView)
[self.child offsetCenterBy:deltaPoint];
self.view.center = CGPointMake(self.view.center.x + deltaPoint.x,
self.view.center.y + deltaPoint.y);
}
- (CGFloat)updateYOffset:(CGFloat)deltaY
{
if (self.child && deltaY < 0)
{
deltaY = [self.child updateYOffset:deltaY];
self.child.view.hidden = deltaY < 0;
self.child.view.hidden = (!self.child.sticky && deltaY < 0);
}
CGFloat newYOffset = self.view.center.y + deltaY;
CGFloat newYCenter = MAX(MIN(self.expandedCenterValue.y, newYOffset), self.contractedCenterValue.y);
self.view.center = CGPointMake(self.expandedCenterValue.x, newYCenter);
if (self.stickyExtensionView)
{
CGFloat newChildYOffset = self.child.view.center.y + deltaY;
CGFloat newChildYCenter = MAX(MIN(self.child.expandedCenterValue.y, newChildYOffset), self.child.contractedCenterValue.y);
self.child.view.center = CGPointMake(self.child.expandedCenterValue.x, newChildYCenter);
}
[self _updateCenter:CGPointMake(self.expandedCenterValue.x, newYCenter)];
CGFloat newAlpha = 1.f - (self.expandedCenterValue.y - self.view.center.y) / self.contractionAmountValue;
newAlpha = MIN(MAX(FLT_EPSILON, newAlpha), 1.f);
@ -136,10 +166,14 @@ const CGFloat contractionVelocity = 300.f;
CGFloat residual = newYOffset - newYCenter;
if (self.child && deltaY > 0 && residual > 0 && !self.stickyExtensionView)
if (self.child && deltaY > 0 && residual > 0)
{
residual = [self.child updateYOffset:residual];
self.child.view.hidden = residual - (newYOffset - newYCenter) > FLT_EPSILON;
self.child.view.hidden = (!self.child.sticky && residual - (newYOffset - newYCenter) > FLT_EPSILON);
}
else if (self.child.sticky && deltaY > 0)
{
[self.child updateYOffset:deltaY];
}
return residual;
@ -182,7 +216,7 @@ const CGFloat contractionVelocity = 300.f;
CGFloat amountToMove = self.expandedCenterValue.y - self.view.center.y;
self.view.center = self.expandedCenterValue;
[self _updateCenter:self.expandedCenterValue];
[self.child expand];
return amountToMove;
@ -192,7 +226,7 @@ const CGFloat contractionVelocity = 300.f;
{
CGFloat amountToMove = self.contractedCenterValue.y - self.view.center.y;
self.view.center = self.contractedCenterValue;
[self _updateCenter:self.contractedCenterValue];
[self.child contract];
return amountToMove;

View File

@ -86,9 +86,29 @@
<segue destination="vXZ-lx-hvc" kind="push" id="iFx-zx-Yj8"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="1" textLabel="WdW-Lh-Cfs" style="IBUITableViewCellStyleDefault" id="TTx-eK-xUp">
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="1" textLabel="2GL-4f-xic" style="IBUITableViewCellStyleDefault" id="dRT-27-ySW">
<rect key="frame" x="0.0" y="130" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="dRT-27-ySW" id="cDy-Ba-zBy">
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="No Extension View Test" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="2GL-4f-xic">
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="Vir-3r-RAn" kind="push" id="8Qt-p1-3tA"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="2" textLabel="WdW-Lh-Cfs" style="IBUITableViewCellStyleDefault" id="TTx-eK-xUp">
<rect key="frame" x="0.0" y="174" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="TTx-eK-xUp" id="N2A-N5-eQc">
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
@ -106,8 +126,28 @@
<segue destination="K7e-Au-F1w" kind="push" id="BJ5-fT-FrY"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="2" textLabel="7pe-uQ-9XE" style="IBUITableViewCellStyleDefault" id="CJy-qF-mnS">
<rect key="frame" x="0.0" y="174" width="320" height="44"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="3" textLabel="WIt-Sx-VLk" style="IBUITableViewCellStyleDefault" id="0y3-Aj-VEQ">
<rect key="frame" x="0.0" y="218" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="0y3-Aj-VEQ" id="w1B-en-E0m">
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
<autoresizingMask key="autoresizingMask"/>
<subviews>
<label opaque="NO" multipleTouchEnabled="YES" contentMode="left" text="Sticky Navbar Test" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" id="WIt-Sx-VLk">
<rect key="frame" x="15" y="0.0" width="270" height="43.5"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<fontDescription key="fontDescription" type="system" pointSize="16"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>
</subviews>
</tableViewCellContentView>
<connections>
<segue destination="7f1-kX-LN4" kind="push" id="YcG-cM-tuL"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" accessoryType="disclosureIndicator" indentationWidth="10" reuseIdentifier="4" textLabel="7pe-uQ-9XE" style="IBUITableViewCellStyleDefault" id="CJy-qF-mnS">
<rect key="frame" x="0.0" y="262" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="CJy-qF-mnS" id="nYc-co-8cU">
<rect key="frame" x="0.0" y="0.0" width="287" height="43.5"/>
@ -126,8 +166,8 @@
<segue destination="YrI-BX-jJR" kind="push" id="6AH-6S-diz"/>
</connections>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="3" textLabel="qz8-f8-ztz" style="IBUITableViewCellStyleDefault" id="cog-xO-RM8">
<rect key="frame" x="0.0" y="218" width="320" height="44"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="5" textLabel="qz8-f8-ztz" style="IBUITableViewCellStyleDefault" id="cog-xO-RM8">
<rect key="frame" x="0.0" y="306" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="cog-xO-RM8" id="bqe-Oi-QQK">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
@ -143,8 +183,8 @@
</subviews>
</tableViewCellContentView>
</tableViewCell>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="4" textLabel="JCj-eZ-ePK" style="IBUITableViewCellStyleDefault" id="lDx-31-RTM">
<rect key="frame" x="0.0" y="262" width="320" height="44"/>
<tableViewCell contentMode="scaleToFill" selectionStyle="default" indentationWidth="10" reuseIdentifier="6" textLabel="JCj-eZ-ePK" style="IBUITableViewCellStyleDefault" id="lDx-31-RTM">
<rect key="frame" x="0.0" y="350" width="320" height="44"/>
<autoresizingMask key="autoresizingMask"/>
<tableViewCellContentView key="contentView" opaque="NO" clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="center" tableViewCell="lDx-31-RTM" id="Pch-9t-ngw">
<rect key="frame" x="0.0" y="0.0" width="320" height="43.5"/>
@ -241,7 +281,7 @@
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="PDI-vm-1dr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="371" y="-532"/>
<point key="canvasLocation" x="783" y="-532"/>
</scene>
<!--View Controller-->
<scene sceneID="WAx-ee-jTN">
@ -301,13 +341,129 @@
</objects>
<point key="canvasLocation" x="-1" y="208"/>
</scene>
<!--View Controller-->
<scene sceneID="zcE-h0-aq3">
<objects>
<viewController id="7f1-kX-LN4" customClass="TLYViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="pUV-UO-fri"/>
<viewControllerLayoutGuide type="bottom" id="POi-6q-Jdv"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="eOj-4e-h2Z">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="p6u-pz-ec0">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="sample" translatesAutoresizingMaskIntoConstraints="NO" id="iiY-8B-e2T">
<rect key="frame" x="0.0" y="0.0" width="320" height="800"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Sz2-8s-bu4">
<rect key="frame" x="35" y="201" width="250" height="35"/>
<fontDescription key="fontDescription" type="system" pointSize="19"/>
<state key="normal" title="Push View Controller">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<segue destination="7f1-kX-LN4" kind="push" id="WRD-ac-CcU"/>
</connections>
</button>
</subviews>
<connections>
<outlet property="delegate" destination="7f1-kX-LN4" id="Em9-iO-CRq"/>
</connections>
</scrollView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstItem="p6u-pz-ec0" firstAttribute="top" secondItem="pUV-UO-fri" secondAttribute="bottom" constant="-64" id="A23-5t-IBv"/>
<constraint firstItem="POi-6q-Jdv" firstAttribute="bottom" secondItem="p6u-pz-ec0" secondAttribute="bottom" id="Jo6-Mp-8tk"/>
<constraint firstItem="p6u-pz-ec0" firstAttribute="leading" secondItem="eOj-4e-h2Z" secondAttribute="leading" id="MTL-4R-N3X"/>
<constraint firstAttribute="trailing" secondItem="p6u-pz-ec0" secondAttribute="trailing" id="N2z-x2-V6b"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="VGK-r1-atg"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="stickyExtensionView" value="NO"/>
<userDefinedRuntimeAttribute type="number" keyPath="fadeBehavior">
<integer key="value" value="1"/>
</userDefinedRuntimeAttribute>
<userDefinedRuntimeAttribute type="boolean" keyPath="stickyNavigationBar" value="YES"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="imageView" destination="iiY-8B-e2T" id="lSi-xq-DXH"/>
<outlet property="scrollView" destination="p6u-pz-ec0" id="jPl-rq-FFo"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="Wqb-OT-maY" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="363" y="208"/>
</scene>
<!--View Controller-->
<scene sceneID="bYR-xs-cnr">
<objects>
<viewController id="Vir-3r-RAn" customClass="TLYViewController" sceneMemberID="viewController">
<layoutGuides>
<viewControllerLayoutGuide type="top" id="BkE-Iq-z6J"/>
<viewControllerLayoutGuide type="bottom" id="8Is-wZ-9BQ"/>
</layoutGuides>
<view key="view" contentMode="scaleToFill" id="0Ja-Wx-zy2">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
<subviews>
<scrollView clipsSubviews="YES" multipleTouchEnabled="YES" contentMode="scaleToFill" ambiguous="YES" translatesAutoresizingMaskIntoConstraints="NO" id="gDa-ud-MJA">
<rect key="frame" x="0.0" y="0.0" width="320" height="568"/>
<subviews>
<imageView userInteractionEnabled="NO" contentMode="scaleToFill" horizontalHuggingPriority="251" verticalHuggingPriority="251" fixedFrame="YES" image="sample" translatesAutoresizingMaskIntoConstraints="NO" id="53M-22-p92">
<rect key="frame" x="0.0" y="0.0" width="320" height="800"/>
</imageView>
<button opaque="NO" contentMode="scaleToFill" fixedFrame="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="Vdy-g9-wQL">
<rect key="frame" x="35" y="201" width="250" height="35"/>
<fontDescription key="fontDescription" type="system" pointSize="19"/>
<state key="normal" title="Push View Controller">
<color key="titleShadowColor" white="0.5" alpha="1" colorSpace="calibratedWhite"/>
</state>
<connections>
<segue destination="Vir-3r-RAn" kind="push" id="fbQ-WQ-fvM"/>
</connections>
</button>
</subviews>
<connections>
<outlet property="delegate" destination="Vir-3r-RAn" id="zC7-46-HJO"/>
</connections>
</scrollView>
</subviews>
<color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
<constraints>
<constraint firstAttribute="trailing" secondItem="gDa-ud-MJA" secondAttribute="trailing" id="0pa-sw-lVw"/>
<constraint firstItem="8Is-wZ-9BQ" firstAttribute="bottom" secondItem="gDa-ud-MJA" secondAttribute="bottom" id="T0T-Y0-yyw"/>
<constraint firstItem="gDa-ud-MJA" firstAttribute="top" secondItem="BkE-Iq-z6J" secondAttribute="bottom" constant="-64" id="WcX-jW-FEV"/>
<constraint firstItem="gDa-ud-MJA" firstAttribute="leading" secondItem="0Ja-Wx-zy2" secondAttribute="leading" id="s51-Ms-zqo"/>
</constraints>
</view>
<navigationItem key="navigationItem" id="ocA-JK-sul"/>
<userDefinedRuntimeAttributes>
<userDefinedRuntimeAttribute type="boolean" keyPath="disableExtensionView" value="YES"/>
</userDefinedRuntimeAttributes>
<connections>
<outlet property="imageView" destination="53M-22-p92" id="uxa-AD-vUc"/>
<outlet property="scrollView" destination="gDa-ud-MJA" id="w2M-m2-Cbo"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="W0g-zW-htj" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="363" y="-532"/>
</scene>
</scenes>
<resources>
<image name="sample" width="320" height="800"/>
</resources>
<inferredMetricsTieBreakers>
<segue reference="6AH-6S-diz"/>
<segue reference="BJ5-fT-FrY"/>
<segue reference="iFx-zx-Yj8"/>
<segue reference="YcG-cM-tuL"/>
<segue reference="6AH-6S-diz"/>
<segue reference="8Qt-p1-3tA"/>
<segue reference="BJ5-fT-FrY"/>
</inferredMetricsTieBreakers>
</document>

View File

@ -29,16 +29,13 @@
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 5;
return 7;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellId = [@(indexPath.row) stringValue];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellId
forIndexPath:indexPath];
return cell;
return [tableView dequeueReusableCellWithIdentifier:cellId forIndexPath:indexPath];
}
@end

View File

@ -10,7 +10,8 @@
@interface TLYViewController ()
/* we set this in the xib as a runtime property */
@property (nonatomic, assign) IBInspectable BOOL disableExtensionView;
@property (nonatomic, assign) IBInspectable BOOL stickyNavigationBar;
@property (nonatomic, assign) IBInspectable BOOL stickyExtensionView;
@property (nonatomic, assign) IBInspectable NSInteger fadeBehavior;
@ -26,6 +27,9 @@
self = [super initWithCoder:aDecoder];
if (self) {
self.disableExtensionView = NO;
self.stickyNavigationBar = NO;
self.stickyExtensionView = NO;
self.fadeBehavior = TLYShyNavBarFadeSubviews;
self.title = @"WTFox Say";
@ -37,13 +41,20 @@
{
[super viewDidLoad];
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 44.f)];
view.backgroundColor = [UIColor redColor];
UIView *view = nil;
if (!self.disableExtensionView)
{
view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 44.f)];
view.backgroundColor = [UIColor redColor];
}
/* Library code */
self.shyNavBarManager.scrollView = self.scrollView;
/* Can then be remove by setting the ExtensionView to nil */
[self.shyNavBarManager setExtensionView:view];
/* Make navbar stick to the top */
[self.shyNavBarManager setStickyNavigationBar:self.stickyNavigationBar];
/* Make the extension view stick to the top */
[self.shyNavBarManager setStickyExtensionView:self.stickyExtensionView];
/* Navigation bar fade behavior */

BIN
resources/ShyNavBar-9.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 433 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 30 KiB

After

Width:  |  Height:  |  Size: 36 KiB