306 lines
11 KiB
Objective-C
306 lines
11 KiB
Objective-C
//
|
|
// YXBaseNavigationController.m
|
|
// healthQuestion
|
|
//
|
|
// Created by xulei on 2022/8/12.
|
|
//
|
|
|
|
#import "YXBaseNavigationController.h"
|
|
#import "XYTransitionProtocol.h"
|
|
#import "XYTransition.h"
|
|
|
|
@interface YXBaseNavigationController ()<UINavigationControllerDelegate,UIGestureRecognizerDelegate>
|
|
|
|
@property (nonatomic, weak) id popDelegate;
|
|
@property (nonatomic,strong) UIPercentDrivenInteractiveTransition *interactivePopTransition;
|
|
@property (nonatomic,strong) UIScreenEdgePanGestureRecognizer *popRecognizer;
|
|
@property(nonatomic,assign) BOOL isSystemSlidBack;//是否开启系统右滑返回
|
|
|
|
@end
|
|
|
|
@implementation YXBaseNavigationController
|
|
|
|
//APP生命周期中 只会执行一次
|
|
+ (void)initialize
|
|
{
|
|
//导航栏主题 title文字属性
|
|
UINavigationBar *navBar = [UINavigationBar appearance];
|
|
//导航栏背景图
|
|
[navBar setBackgroundImage:[UIImage imageNamed:@"navBackImg"] forBarMetrics:UIBarMetricsDefault];
|
|
[navBar setBarTintColor:KWhiteColor];
|
|
[navBar setTintColor:UIColorHex(#21BEBD)];
|
|
[navBar setTitleTextAttributes:@{NSForegroundColorAttributeName :KWhiteColor, NSFontAttributeName : [UIFont systemFontOfSize:18]}];
|
|
[navBar setBackgroundImage:[UIImage imageWithColor:UIColorHex(#21BEBD)] forBarPosition:UIBarPositionAny barMetrics:UIBarMetricsDefault];
|
|
|
|
if (@available(iOS 15.0,*) ) {
|
|
UINavigationBarAppearance *apperance = [[UINavigationBarAppearance alloc]init];
|
|
|
|
[apperance configureWithOpaqueBackground];// 重置背景和阴影颜色
|
|
|
|
apperance.backgroundColor = UIColorHex(#21BEBD);
|
|
|
|
apperance.backgroundEffect = nil;
|
|
|
|
// 去除导航栏阴影(如果不设置clear,导航栏底下会有一条阴影线)
|
|
|
|
apperance.shadowColor = [UIColor clearColor];
|
|
|
|
[apperance setShadowImage:[UIImage imageWithColor:[UIColor clearColor]]];
|
|
|
|
[apperance setTitleTextAttributes:@{NSForegroundColorAttributeName :KWhiteColor, NSFontAttributeName : [UIFont systemFontOfSize:18]}];
|
|
|
|
[[UINavigationBar appearance]setStandardAppearance:apperance];
|
|
|
|
[[UINavigationBar appearance]setScrollEdgeAppearance:apperance];
|
|
|
|
}else{
|
|
|
|
|
|
|
|
[[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName :KWhiteColor, NSFontAttributeName : [UIFont systemFontOfSize:18]}];
|
|
|
|
[[UINavigationBar appearance] setBarTintColor:UIColorHex(#21BEBD)];
|
|
|
|
[[UINavigationBar appearance] setShadowImage:[UIImage new]];
|
|
|
|
|
|
|
|
}
|
|
[UITabBar appearance].translucent = NO;
|
|
}
|
|
|
|
- (void)viewDidLoad {
|
|
[super viewDidLoad];
|
|
self.popDelegate = self.interactivePopGestureRecognizer.delegate;
|
|
self.delegate = self;
|
|
|
|
//默认开启系统右划返回
|
|
self.interactivePopGestureRecognizer.enabled = YES;
|
|
self.interactivePopGestureRecognizer.delegate = self;
|
|
|
|
//只有在使用转场动画时,禁用系统手势,开启自定义右划手势
|
|
_popRecognizer = [[UIScreenEdgePanGestureRecognizer alloc] initWithTarget:self action:@selector(handleNavigationTransition:)];
|
|
//下面是全屏返回
|
|
// _popRecognizer = [[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handleNavigationTransition:)];
|
|
_popRecognizer.edges = UIRectEdgeLeft;
|
|
[_popRecognizer setEnabled:NO];
|
|
[self.view addGestureRecognizer:_popRecognizer];
|
|
}
|
|
|
|
//解决手势失效问题
|
|
- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
|
{
|
|
if (_isSystemSlidBack) {
|
|
self.interactivePopGestureRecognizer.enabled = YES;
|
|
[_popRecognizer setEnabled:NO];
|
|
}else{
|
|
self.interactivePopGestureRecognizer.enabled = NO;
|
|
[_popRecognizer setEnabled:YES];
|
|
}
|
|
}
|
|
|
|
//根视图禁用右划返回
|
|
-(BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
|
|
return self.childViewControllers.count == 1 ? NO : YES;
|
|
}
|
|
|
|
//push时隐藏tabbar
|
|
- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
|
|
{
|
|
if (self.viewControllers.count > 0) {
|
|
if ([viewController conformsToProtocol:@protocol(XYTransitionProtocol)] && [self isNeedTransition:viewController]) {
|
|
viewController.hidesBottomBarWhenPushed = NO;
|
|
}else{
|
|
viewController.hidesBottomBarWhenPushed = YES;
|
|
}
|
|
|
|
}
|
|
[super pushViewController:viewController animated:animated];
|
|
// 修改tabBra的frame
|
|
CGRect frame = self.tabBarController.tabBar.frame;
|
|
frame.origin.y = [UIScreen mainScreen].bounds.size.height - frame.size.height;
|
|
self.tabBarController.tabBar.frame = frame;
|
|
}
|
|
|
|
-(void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated{
|
|
|
|
if ([viewController isKindOfClass:[YXBaseViewController class]]) {
|
|
YXBaseViewController * vc = (YXBaseViewController *)viewController;
|
|
if (vc.isHidenNaviBar) {
|
|
vc.view.top = 0;
|
|
[vc.navigationController setNavigationBarHidden:YES animated:animated];
|
|
}else{
|
|
vc.view.top = kTopHeight;
|
|
[vc.navigationController setNavigationBarHidden:NO animated:animated];
|
|
}
|
|
}
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* 返回到指定的类视图
|
|
*
|
|
* @param ClassName 类名
|
|
* @param animated 是否动画
|
|
*/
|
|
-(BOOL)popToAppointViewController:(NSString *)ClassName animated:(BOOL)animated
|
|
{
|
|
id vc = [self getCurrentViewControllerClass:ClassName];
|
|
if(vc != nil && [vc isKindOfClass:[UIViewController class]])
|
|
{
|
|
[self popToViewController:vc animated:animated];
|
|
return YES;
|
|
}
|
|
|
|
return NO;
|
|
}
|
|
|
|
/*!
|
|
* 获得当前导航器显示的视图
|
|
*
|
|
* @param ClassName 要获取的视图的名称
|
|
*
|
|
* @return 成功返回对应的对象,失败返回nil;
|
|
*/
|
|
-(instancetype)getCurrentViewControllerClass:(NSString *)ClassName
|
|
{
|
|
Class classObj = NSClassFromString(ClassName);
|
|
|
|
NSArray * szArray = self.viewControllers;
|
|
for (id vc in szArray) {
|
|
if([vc isMemberOfClass:classObj])
|
|
{
|
|
return vc;
|
|
}
|
|
}
|
|
|
|
return nil;
|
|
}
|
|
|
|
|
|
-(UIViewController *)childViewControllerForStatusBarStyle{
|
|
return self.topViewController;
|
|
}
|
|
|
|
|
|
#pragma mark ————— 转场动画区 —————
|
|
|
|
//navigation切换是会走这个代理
|
|
-(id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController animationControllerForOperation:(UINavigationControllerOperation)operation fromViewController:(UIViewController *)fromVC toViewController:(UIViewController *)toVC
|
|
{
|
|
NSLog(@"转场动画代理方法");
|
|
self.isSystemSlidBack = YES;
|
|
//如果来源VC和目标VC都实现协议,那么都做动画
|
|
if ([fromVC conformsToProtocol:@protocol(XYTransitionProtocol)] && [toVC conformsToProtocol:@protocol(XYTransitionProtocol)]) {
|
|
|
|
BOOL pinterestNedd = [self isNeedTransition:fromVC:toVC];
|
|
XYTransition *transion = [XYTransition new];
|
|
if (operation == UINavigationControllerOperationPush && pinterestNedd) {
|
|
transion.isPush = YES;
|
|
|
|
//暂时屏蔽带动画的右划返回
|
|
self.isSystemSlidBack = NO;
|
|
// self.isSystemSlidBack = YES;
|
|
}
|
|
else if(operation == UINavigationControllerOperationPop && pinterestNedd)
|
|
{
|
|
//暂时屏蔽带动画的右划返回
|
|
// return nil;
|
|
|
|
transion.isPush = NO;
|
|
self.isSystemSlidBack = NO;
|
|
}
|
|
else{
|
|
return nil;
|
|
}
|
|
return transion;
|
|
}else if([toVC conformsToProtocol:@protocol(XYTransitionProtocol)]){
|
|
//如果只有目标VC开启动画,那么isSystemSlidBack也要随之改变
|
|
BOOL pinterestNedd = [self isNeedTransition:toVC];
|
|
self.isSystemSlidBack = !pinterestNedd;
|
|
return nil;
|
|
}
|
|
return nil;
|
|
}
|
|
|
|
//判断fromVC和toVC是否需要实现pinterest效果
|
|
-(BOOL)isNeedTransition:(UIViewController<XYTransitionProtocol> *)fromVC :(UIViewController<XYTransitionProtocol> *)toVC
|
|
{
|
|
BOOL a = NO;
|
|
BOOL b = NO;
|
|
if ([fromVC respondsToSelector:@selector(isNeedTransition)] && [fromVC isNeedTransition]) {
|
|
a = YES;
|
|
}
|
|
if ([toVC respondsToSelector:@selector(isNeedTransition)] && [toVC isNeedTransition]) {
|
|
b = YES;
|
|
}
|
|
return (a && b) ;
|
|
|
|
}
|
|
//判断fromVC和toVC是否需要实现pinterest效果
|
|
-(BOOL)isNeedTransition:(UIViewController<XYTransitionProtocol> *)toVC
|
|
{
|
|
BOOL b = NO;
|
|
if ([toVC respondsToSelector:@selector(isNeedTransition)] && [toVC isNeedTransition]) {
|
|
b = YES;
|
|
}
|
|
return b;
|
|
|
|
}
|
|
|
|
#pragma mark -- NavitionContollerDelegate
|
|
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
|
|
interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController
|
|
{
|
|
if (!self.interactivePopTransition) { return nil; }
|
|
return self.interactivePopTransition;
|
|
}
|
|
|
|
|
|
#pragma mark UIGestureRecognizer handlers
|
|
|
|
- (void)handleNavigationTransition:(UIScreenEdgePanGestureRecognizer*)recognizer
|
|
{
|
|
CGFloat progress = [recognizer translationInView:self.view].x / (self.view.bounds.size.width);
|
|
// progress = MIN(1.0, MAX(0.0, progress));
|
|
NSLog(@"右划progress %.2f",progress);
|
|
|
|
if (recognizer.state == UIGestureRecognizerStateBegan) {
|
|
self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
|
|
[self popViewControllerAnimated:YES];
|
|
}
|
|
else if (recognizer.state == UIGestureRecognizerStateChanged) {
|
|
[self.interactivePopTransition updateInteractiveTransition:progress];
|
|
}
|
|
else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
|
|
CGPoint velocity = [recognizer velocityInView:recognizer.view];
|
|
|
|
if (progress > 0.5 || velocity.x >100) {
|
|
[self.interactivePopTransition finishInteractiveTransition];
|
|
}
|
|
else {
|
|
[self.interactivePopTransition cancelInteractiveTransition];
|
|
}
|
|
self.interactivePopTransition = nil;
|
|
}
|
|
}
|
|
|
|
|
|
- (void)didReceiveMemoryWarning {
|
|
[super didReceiveMemoryWarning];
|
|
// Dispose of any resources that can be recreated.
|
|
}
|
|
|
|
/*
|
|
#pragma mark - Navigation
|
|
|
|
// In a storyboard-based application, you will often want to do a little preparation before navigation
|
|
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
|
|
// Get the new view controller using [segue destinationViewController].
|
|
// Pass the selected object to the new view controller.
|
|
}
|
|
*/
|
|
|
|
@end
|