OK, I am just sick of this... Going to implement the simple Facebook UX

This commit is contained in:
Mazyad Alabduljaleel 2014-06-16 17:14:51 +04:00
parent 69cafa08ba
commit 6be2ee4a07
3 changed files with 42 additions and 88 deletions

View File

@ -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

View File

@ -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;

View File

@ -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];
}