Initial commit
This commit is contained in:
+39
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// NTESNavigationAnimator.h
|
||||
// NIM
|
||||
//
|
||||
// Created by chris on 16/1/31.
|
||||
// Copyright © 2016年 Netease. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
typedef NS_ENUM(NSInteger, NTESNavigationAnimationType) {
|
||||
NTESNavigationAnimationTypeNormal,
|
||||
NTESNavigationAnimationTypeCross,
|
||||
};
|
||||
|
||||
@class NTESNavigationAnimator;
|
||||
|
||||
@protocol NTESNavigationAnimatorDelegate <NSObject>
|
||||
|
||||
- (void)animationWillStart:(NTESNavigationAnimator *)animator;
|
||||
|
||||
- (void)animationDidEnd:(NTESNavigationAnimator *)animator;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@interface NTESNavigationAnimator : NSObject <UIViewControllerAnimatedTransitioning>
|
||||
|
||||
@property (nonatomic,weak) UINavigationController *navigationController;
|
||||
|
||||
@property (nonatomic,assign) UINavigationControllerOperation currentOpearation;
|
||||
|
||||
@property (nonatomic,assign) NTESNavigationAnimationType animationType;
|
||||
|
||||
@property (nonatomic,weak) id<NTESNavigationAnimatorDelegate> delegate;
|
||||
|
||||
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController;
|
||||
|
||||
@end
|
||||
+150
@@ -0,0 +1,150 @@
|
||||
//
|
||||
// NTESNavigationAnimator.m
|
||||
// NIM
|
||||
//
|
||||
// Created by chris on 16/1/31.
|
||||
// Copyright © 2016年 Netease. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NTESNavigationAnimator.h"
|
||||
#import "UIView+NTES.h"
|
||||
//#import "NTESMainTabController.h"
|
||||
#import "IfishMianTabViewController.h"
|
||||
|
||||
@implementation NTESNavigationAnimator
|
||||
|
||||
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_navigationController = navigationController;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext
|
||||
{
|
||||
return 0.35;
|
||||
}
|
||||
|
||||
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext
|
||||
{
|
||||
|
||||
switch (self.currentOpearation) {
|
||||
case UINavigationControllerOperationPop:
|
||||
[self popAnimation:transitionContext];
|
||||
break;
|
||||
case UINavigationControllerOperationPush:
|
||||
[self pushAnimation:transitionContext];
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
- (void)pushAnimation:(id<UIViewControllerContextTransitioning>)transitionContext
|
||||
{
|
||||
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
|
||||
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
|
||||
|
||||
UIView *containerView = [transitionContext containerView];
|
||||
UINavigationController *navigationController = fromViewController.navigationController;
|
||||
UITabBarController *tabbarController = fromViewController.tabBarController;
|
||||
//使用xib可能会出现view的size不对的情况
|
||||
CGRect frame = fromViewController.view.frame;
|
||||
if ((toViewController.edgesForExtendedLayout & UIRectEdgeTop) == 0)
|
||||
{
|
||||
frame = CGRectOffset(navigationController.view.frame, 0, navigationController.navigationBar.bottom);
|
||||
}
|
||||
if ((toViewController.edgesForExtendedLayout & UIRectEdgeBottom) == 0) {
|
||||
CGRect slice = CGRectZero;
|
||||
CGRect remainder = CGRectZero;
|
||||
CGRectDivide(frame, &slice, &remainder, tabbarController.tabBar.height, CGRectMaxYEdge);
|
||||
frame = remainder;
|
||||
}
|
||||
toViewController.view.frame = frame;
|
||||
|
||||
[containerView addSubview:fromViewController.view];
|
||||
[containerView addSubview:toViewController.view];
|
||||
|
||||
|
||||
CGFloat width = containerView.width;
|
||||
toViewController.view.left = width;
|
||||
|
||||
[self callAnimationWillStart];
|
||||
CGFloat duration = [self transitionDuration:transitionContext];
|
||||
|
||||
[UIView animateWithDuration:duration animations:^{
|
||||
fromViewController.view.right = width * 0.5;
|
||||
toViewController.view.right = width;
|
||||
} completion:^(BOOL finished) {
|
||||
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
|
||||
[self callAnimationDidEnd];
|
||||
}];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)popAnimation:(id<UIViewControllerContextTransitioning>)transitionContext
|
||||
{
|
||||
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
|
||||
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
|
||||
CGFloat snapshootHeight = [UIApplication sharedApplication].statusBarFrame.size.height + fromViewController.navigationController.navigationBar.height;
|
||||
|
||||
UIView *fakeBar = [fromViewController.navigationController.view
|
||||
resizableSnapshotViewFromRect:CGRectMake(0, 0,fromViewController.view.width, snapshootHeight) afterScreenUpdates:NO withCapInsets:UIEdgeInsetsZero];
|
||||
UINavigationBar *tureBar = toViewController.navigationController.navigationBar;
|
||||
|
||||
BOOL hidesBottomBar = toViewController.hidesBottomBarWhenPushed && self.navigationController.viewControllers.firstObject != toViewController;
|
||||
|
||||
UITabBar *tabbar = [IfishMianTabViewController instance].tabBar;
|
||||
UIView *containerView = [transitionContext containerView];
|
||||
|
||||
[containerView addSubview:toViewController.view];
|
||||
if (!hidesBottomBar) {
|
||||
[containerView addSubview:tabbar];
|
||||
}
|
||||
if (self.animationType == NTESNavigationAnimationTypeCross) {
|
||||
[containerView addSubview:tureBar];
|
||||
[fromViewController.view addSubview:fakeBar];
|
||||
}
|
||||
[containerView addSubview:fromViewController.view];
|
||||
|
||||
|
||||
CGFloat width = containerView.width;
|
||||
|
||||
toViewController.view.right = width * 0.5;
|
||||
tabbar.right = width * 0.5;
|
||||
|
||||
[self callAnimationWillStart];
|
||||
CGFloat duration = [self transitionDuration:transitionContext];
|
||||
[UIView animateWithDuration:duration animations:^{
|
||||
fromViewController.view.left = width;
|
||||
toViewController.view.right = width;
|
||||
tabbar.right = width;
|
||||
fakeBar.alpha = 0.0;
|
||||
} completion:^(BOOL finished) {
|
||||
[[IfishMianTabViewController instance].view addSubview:tabbar];
|
||||
[toViewController.navigationController.view addSubview:tureBar];
|
||||
[fakeBar removeFromSuperview];
|
||||
[transitionContext completeTransition:![transitionContext transitionWasCancelled]];
|
||||
[self callAnimationDidEnd];
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)callAnimationWillStart
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(animationWillStart:)]) {
|
||||
[self.delegate animationWillStart:self];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)callAnimationDidEnd
|
||||
{
|
||||
if ([self.delegate respondsToSelector:@selector(animationDidEnd:)]) {
|
||||
[self.delegate animationDidEnd:self];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
+17
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// NTESNavigationHandler.h
|
||||
// NIM
|
||||
//
|
||||
// Created by chris on 16/1/28.
|
||||
// Copyright © 2016年 Netease. All rights reserved.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
@interface NTESNavigationHandler : NSObject<UINavigationControllerDelegate>
|
||||
|
||||
@property (nonatomic,strong,readonly) UIPanGestureRecognizer *recognizer;
|
||||
|
||||
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController;
|
||||
|
||||
@end
|
||||
+185
@@ -0,0 +1,185 @@
|
||||
//
|
||||
// NTESNavigationHandler.m
|
||||
// NIM
|
||||
//
|
||||
// Created by chris on 16/1/28.
|
||||
// Copyright © 2016年 Netease. All rights reserved.
|
||||
//
|
||||
|
||||
#import "NTESNavigationHandler.h"
|
||||
#import "UIView+NTES.h"
|
||||
//#import "NTESMainTabController.h"
|
||||
#import "IfishMianTabViewController.h"
|
||||
#import "UIResponder+NTESFirstResponder.h"
|
||||
#import "NTESNavigationAnimator.h"
|
||||
|
||||
@interface NTESNavigationHandler()<UIGestureRecognizerDelegate,NTESNavigationAnimatorDelegate>
|
||||
|
||||
@property (nonatomic,strong) UIPercentDrivenInteractiveTransition* interaction;
|
||||
|
||||
@property (nonatomic,weak) UINavigationController *navigationController;
|
||||
|
||||
@property (nonatomic,strong) NTESNavigationAnimator *animator;
|
||||
|
||||
@property (nonatomic,assign) UINavigationControllerOperation currentOperation;
|
||||
|
||||
@property (nonatomic,strong) CAGradientLayer *uiPopShadow;
|
||||
|
||||
@property (nonatomic,assign) BOOL isAnimating;
|
||||
|
||||
@end
|
||||
|
||||
@implementation NTESNavigationHandler
|
||||
|
||||
- (instancetype)initWithNavigationController:(UINavigationController *)navigationController
|
||||
{
|
||||
self = [super init];
|
||||
if (self) {
|
||||
_recognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(pan:)];
|
||||
_recognizer.delegate = self;
|
||||
_recognizer.delaysTouchesBegan = NO;
|
||||
[navigationController.view addGestureRecognizer:_recognizer];
|
||||
_animator = [[NTESNavigationAnimator alloc] initWithNavigationController:navigationController];
|
||||
_animator.delegate = self;
|
||||
_navigationController = navigationController;
|
||||
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)pan:(UIPanGestureRecognizer*)recognizer
|
||||
{
|
||||
UIView* view = recognizer.view;
|
||||
switch (recognizer.state) {
|
||||
case UIGestureRecognizerStateBegan:{
|
||||
CGPoint location = [recognizer locationInView:view];
|
||||
if (location.x < CGRectGetMidX(view.bounds) && self.navigationController.viewControllers.count > 1) { // left half
|
||||
self.interaction = [UIPercentDrivenInteractiveTransition new];
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
}
|
||||
break;
|
||||
case UIGestureRecognizerStateChanged:{
|
||||
CGPoint translation = [recognizer translationInView:view];
|
||||
CGFloat d = translation.x / view.width;
|
||||
[self.interaction updateInteractiveTransition:d];
|
||||
}
|
||||
break;
|
||||
case UIGestureRecognizerStateEnded:
|
||||
case UIGestureRecognizerStateCancelled:{
|
||||
if ([recognizer locationInView:view].x > view.width * .5f) {
|
||||
[self.interaction finishInteractiveTransition];
|
||||
} else {
|
||||
[self.interaction cancelInteractiveTransition];
|
||||
}
|
||||
self.interaction = nil;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - UINavigationControllerDelegate
|
||||
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
|
||||
- (nullable id <UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
|
||||
interactionControllerForAnimationController:(id <UIViewControllerAnimatedTransitioning>) animationController
|
||||
{
|
||||
return self.interaction;
|
||||
}
|
||||
|
||||
|
||||
- (nullable id <UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
|
||||
animationControllerForOperation:(UINavigationControllerOperation)operation
|
||||
fromViewController:(UIViewController *)fromVC
|
||||
toViewController:(UIViewController *)toVC
|
||||
{
|
||||
self.currentOperation = operation;
|
||||
self.animator.currentOpearation = operation;
|
||||
BOOL cross = [self isUseClearBar:fromVC] || [self isUseClearBar:toVC];
|
||||
self.animator.animationType = cross ? NTESNavigationAnimationTypeCross : NTESNavigationAnimationTypeNormal;
|
||||
|
||||
if (operation == UINavigationControllerOperationPop) {
|
||||
[fromVC.view.layer addSublayer:self.uiPopShadow];
|
||||
}
|
||||
return self.animator;
|
||||
}
|
||||
|
||||
#pragma mark - UIGestureRecognizerDelegate
|
||||
|
||||
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer
|
||||
{
|
||||
BOOL forbid = [self isForbidInteractivePop:self.navigationController.topViewController];
|
||||
if (forbid || self.isAnimating) {
|
||||
return NO;
|
||||
}
|
||||
UIView* view = gestureRecognizer.view;
|
||||
CGPoint location = [gestureRecognizer locationInView:view];
|
||||
return location.x < 44.f;
|
||||
}
|
||||
|
||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRequireFailureOfGestureRecognizer:(nonnull UIGestureRecognizer *)otherGestureRecognizer
|
||||
{
|
||||
return [otherGestureRecognizer.view.superview isKindOfClass:[UITableView class]];
|
||||
}
|
||||
|
||||
|
||||
|
||||
#pragma mark - Get
|
||||
- (CAGradientLayer *)uiPopShadow
|
||||
{
|
||||
if (!_uiPopShadow) {
|
||||
_uiPopShadow = [CAGradientLayer layer];
|
||||
_uiPopShadow.frame = CGRectMake(-6, 0, 6, [IfishMianTabViewController instance].view.frame.size.height);
|
||||
_uiPopShadow.startPoint = CGPointMake(1.0, 0.5);
|
||||
_uiPopShadow.endPoint = CGPointMake(0, 0.5);
|
||||
_uiPopShadow.colors = [NSArray arrayWithObjects:(id)[[UIColor colorWithWhite:0.0 alpha:0.2f] CGColor], (id)[[UIColor clearColor] CGColor], nil];
|
||||
}
|
||||
return _uiPopShadow;
|
||||
}
|
||||
|
||||
#pragma mark - NTESNavigationAnimatorDelegate
|
||||
- (void)animationWillStart:(NTESNavigationAnimator *)animator
|
||||
{
|
||||
self.isAnimating = YES;
|
||||
}
|
||||
|
||||
- (void)animationDidEnd:(NTESNavigationAnimator *)animator
|
||||
{
|
||||
self.isAnimating = NO;
|
||||
}
|
||||
|
||||
#pragma mark - Private
|
||||
- (BOOL)isUseClearBar:(UIViewController *)vc
|
||||
{
|
||||
SEL sel = NSSelectorFromString(@"useClearBar");
|
||||
BOOL use = NO;
|
||||
if ([vc respondsToSelector:sel]) {
|
||||
SuppressPerformSelectorLeakWarning(use = (BOOL)[vc performSelector:sel]);
|
||||
}
|
||||
return use;
|
||||
}
|
||||
|
||||
- (BOOL)isForbidInteractivePop:(UIViewController *)vc{
|
||||
SEL sel = NSSelectorFromString(@"forbidInteractivePop");
|
||||
BOOL use = NO;
|
||||
if ([vc respondsToSelector:sel]) {
|
||||
SuppressPerformSelectorLeakWarning(use = (BOOL)[vc performSelector:sel]);
|
||||
}
|
||||
return use;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
Reference in New Issue
Block a user