添加全屏側滑返回 1.獲取到系統的pop返回手勢 2.獲取pop在哪個view上 3.獲取target,action 4.自定義UIPanGestureRecognizer
//1.獲取手勢
guard let pop = interactivePopGestureRecognizer else { return }
//2.獲取手勢的view
guard let gesView = pop.view else { return }
//3.獲取target/action
let targets = pop.value(forKey: "_targets") as? [NSObject]
let targetObj = targets?.first
if targetObj == nil { return }
//3.1.target
guard let target = targetObj?.value(forKey: "target") else { return }
//3.2.取出Action
let action = Selector(("handleNavigationTransition:"))
//4.自己創建手勢
let pan = UIPanGestureRecognizer(target: target, action: action)
gesView.addGestureRecognizer(pan)
1.關於導航欄左右兩邊的按鈕
1.隱藏導航欄上的返回字體 //Swift UIBarButtonItem.appearance().setBackButtonTitlePositionAdjustment(UIOffsetMake(0, -60), forBarMetrics: .Default) //OC [[UIBarButtonItem appearance] setBackButtonTitlePositionAdjustment:UIOffsetMake(0, -60) forBarMetrics:UIBarMetricsDefault]; //設置導航欄右邊有2個按鈕 UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:view]; self.navigationItem.rightBarButtonItem = item; 系統默認的rightBarButtonItem邊距 self.navigationItem.leftBarButtonItem.imageInsets = UIEdgeInsetsMake(0,-20,0,0); self.navigationItem.rightBarButtonItem.imageInsets = UIEdgeInsetsMake(0,-10,0,10); //使左邊導航欄按鈕位置更加左邊一點 { UIView *left = [[UIView alloc] init]; left.frame = CGRectMake(0, 0, 0, 1); UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:left]; //使導航欄按鈕位置更加左邊或者右邊 UIBarButtonItem *nagetiveSpacer = [[UIBarButtonItem alloc]initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; nagetiveSpacer.width = -40;//這個值可以根據自己需要自己調整 self.navigationItem.leftBarButtonItems = @[nagetiveSpacer,item]; } UIBarButtonItem *item = [[UIBarButtonItem alloc] initWithCustomView:back]; item.width = -20;
2.修改標題
//標題顏色 self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor someColor]} //設置了導航條背景顏色,會導致按鈕標題顏色改變,通過以下方法修改 導航欄子控件顏色 self.navigationController.navigationBar.tintColor = [UIColor someColor]; 修改導航條背景顏色 self.navigationController.navigationBar.barTintColor = [UIColor colorWithHexString:@"#2295f2"];
//設置導航控制器標題的顏色和字體大小等
NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:
[UIColor whiteColor],NSForegroundColorAttributeName,
[UIFont systemFontOfSize:17],NSFontAttributeName,nil];
[self.navigationController.navigationBar setTitleTextAttributes:attributes];
3.在滑動過程中隱藏navigationbar
(1) 像safari self.navigationController.hidesBarsOnSwipe = YES; (2) - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetY = scrollView.contentOffset.y + __tableView.contentInset.top; CGFloat panTranslationY = [scrollView.panGestureRecognizer translationInView:self.tableView].y; if (offsetY > 64) { if (panTranslationY > 0) { //下滑趨勢,顯示 [self.navigationController setNavigationBarHidden:NO animated:YES]; } else { //上滑趨勢,隱藏 [self.navigationController setNavigationBarHidden:YES animated:YES]; } } else { [self.navigationController setNavigationBarHidden:NO animated:YES]; } } 這里的offsetY > 64只是為了在視圖滑過navigationBar的高度之后才開始處理,防止影響展示效果。panTranslationY是scrollView的pan手勢的手指位置的y值,可能不是太好,因為panTranslationY這個值在較小幅度上下滑動時,可能都為正或都為負,這就使得這一方式不太靈敏. (3).當我們的手離開屏幕時候隱藏 - (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset { if(velocity.y > 0) { [self.navigationController setNavigationBarHidden:YES animated:YES]; } else { [self.navigationController setNavigationBarHidden:NO animated:YES]; } } velocity.y這個量,在上滑和下滑時,變化極小(小數),但是因為方向不同,有正負之分,這就很好處理了。
4.設置導航欄透明度
//第一種navigationBar根據滑動距離的漸變色實現 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetToShow = 200.0;//滑動多少就完全顯示 CGFloat alpha = 1 - (offsetToShow - scrollView.contentOffset.y) / offsetToShow; [[self.navigationController.navigationBar subviews] objectAtIndex:0].alpha = alpha; } //第二種 - (void)scrollViewDidScroll:(UIScrollView *)scrollView { CGFloat offsetToShow = 200.0; CGFloat alpha = 1 - (offsetToShow - scrollView.contentOffset.y) / offsetToShow; [self.navigationController.navigationBar setShadowImage:[UIImage new]]; [self.navigationController.navigationBar setBackgroundImage:[self imageWithColor:[[UIColor orangeColor]colorWithAlphaComponent:alpha]] forBarMetrics:UIBarMetricsDefault]; } //生成一張純色的圖片 - (UIImage *)imageWithColor:(UIColor *)color { CGRect rect = CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); UIGraphicsBeginImageContext(rect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [color CGColor]); CGContextFillRect(context, rect); UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); return theImage; } 設置導航欄透明 //方法一:設置透明度 [[[self.navigationController.navigationBar subviews]objectAtIndex:0] setAlpha:0.1]; //方法二:設置背景圖片 /** * 設置導航欄,使其透明 * */ - (void)setNavigationBarColor:(UIColor *)color targetController:(UIViewController *)targetViewController{ //導航條的顏色 以及隱藏導航條的顏色targetViewController.navigationController.navigationBar.shadowImage = [[UIImage alloc]init]; CGRect rect=CGRectMake(0.0f, 0.0f, 1.0f, 1.0f); UIGraphicsBeginImageContext(rect.size); CGContextRef context = UIGraphicsGetCurrentContext(); CGContextSetFillColorWithColor(context, [color CGColor]); CGContextFillRect(context, rect); UIImage *theImage = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); [targetViewController.navigationController.navigationBar setBackgroundImage:theImage forBarMetrics:UIBarMetricsDefault]; } //3 //設置一張空的圖片 [self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc]init] forBarMetrics:UIBarMetricsDefault]; //清除邊框,設置一張空的圖片(隱藏底部陰影條,傳遞一個空圖片的UIImage對象),底部的黑線 [self.navigationController.navigationBar setShadowImage:[[UIImage alloc]init]]; //是否透明 self.navigationController.navigationBar.translucent = YES;
5.滑動返回手勢
//關閉navigationController的滑動返回手勢 //第一種 self.navigationController.interactivePopGestureRecognizer.enabled = NO; //第二種 id target = self.navigationController.interactivePopGestureRecognizer.delegate; UIPanGestureRecognizer *pan = [[UIPanGestureRecognizer alloc] initWithTarget:target action:nil]; [self.view addGestureRecognizer:pan]; //解決導航控制器pop手勢失效 self.interactivePopGestureRecognizer.delegate = self; - (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer { // 手勢何時有效 : 當導航控制器的子控制器個數 > 1就有效 return self.childViewControllers.count > 1; }
6.導航欄的隱藏顯示問題(正確的姿勢)
1.// 設置導航控制器的代理為self self.navigationController.delegate = self; 2.<UINavigationControllerDelegate> 3.// 將要顯示控制器 - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated { // 判斷要顯示的控制器是否是自己 BOOL isShowHomePage = [viewController isKindOfClass:[self class]]; [self.navigationController setNavigationBarHidden:isShowHomePage animated:YES]; }
7.修改pop回來的頁面
#warning 寫在 C 的 viewDidLoad() 方法中 //A push 到 B, B push 到 C, C pop 到 D,D 再 pop到 A // 建立可變拷貝對象,然后進行替換操作 NSMutableArray *navChildMArr = [self.navigationController.childViewControllers mutableCopy]; [navChildMArr replaceObjectAtIndex:1 withObject:D]; // 當然,最后再將替換后的數組賦值回去不要忘了 [self.navigationController setViewControllers:navChildMArr animated:YES]; 自定義導航欄:https://github.com/zhangjie579/IWNavigationController
8.關於push,pop,model,dimiss
遍歷popToViewController跳轉的控制器,然后跳到指定位置 for (int i = 0; i<self.navigationController.viewControllers.count; i++) { UIViewController * controller = self.navigationController.viewControllers[i]; if ([controller isKindOfClass:InformMainViewController.class]) { InformMainViewController * vc = (InformMainViewController *)controller; [self.navigationController popToViewController:vc animated:YES]; break; } } pop回指定控制器 1. NSArray *viewControllers=[self.navigationController viewControllers]; 2. UIViewController *controller=[viewControllers objectAtIndex:1]; 3. [self.navigationController popToViewController:controller animated:YES]; 3.關於push,pop,model,dimiss 1.注意:如果用stroyboard的話,要拉線,不然可能會出現不了界面!!! [self performSegueWithIdentifier:@"MyApply-To-FlowDetail" sender:nil]; //跳轉前傳值 -(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"MyApply-To-FlowDetail"]) { FlowDetailController * controller = segue.destinationViewController; if (_bool_fromApply) { controller.flow_id = _flow_id; } else { controller.flow_id = _flowInfoModel.id; } controller.delegate = self; } } 2.第二種方法 UIStoryboard *story = [UIStoryboard storyboardWithName:@"My" bundle:nil]; MyEnterCompanyNameController *vc = (MyEnterCompanyNameController *)[story instantiateViewControllerWithIdentifier:@"MyEnterCompanyName"]; [self.navigationController pushViewController:vc animated:YES]; 4.設置轉場動畫modalTransitionStyle 1.系統的
vc.vcType = ViewControllerTypeFindName;
// [self.navigationController pushViewController:vc animated:YES];
IWNavigationController *nav = [[IWNavigationController alloc] initWithRootViewController:vc];
[IWNavigationController setupWithType:IWNavTypeWhite];
//nav.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;//直接進入頁面,無動畫效果
nav.modalTransitionStyle = UIModalTransitionStylePartialCurl;//翻頁
[self presentViewController:nav animated:YES completion:nil];
2.自定義的
CATransition *animation = [CATransition animation];
[animation setDuration:0.5];
[animation setType:kCATransitionPush];
[animation setSubtype:kCATransitionFromRight];
[animation setTimingFunction:[CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut]];
[self.view.window.layer addAnimation:animation forKey:@"LoginViewController"]; // 添加動作
ForgetNameViewController *vc = [[ForgetNameViewController alloc] init];
vc.vcType = ViewControllerTypeFindName;
IWNavigationController *nav = [[IWNavigationController alloc] initWithRootViewController:vc];
[IWNavigationController setupWithType:IWNavTypeWhite];
[self presentViewController:nav animated:NO completion:^{
[self.view.window.layer removeAnimationForKey:@"LoginViewController"];
}];
