OK, I am just sick of this... Going to implement the simple Facebook UX
This commit is contained in:
parent
69cafa08ba
commit
6be2ee4a07
|
|
@ -22,6 +22,8 @@ static inline CGFloat AACStatusBarHeight()
|
|||
@interface TLYShyNavBarManager () <UIGestureRecognizerDelegate>
|
||||
|
||||
@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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
}
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue