ios UINavigationController 導航欄


添加全屏側滑返回
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.系統的
ForgetNameViewController *vc = [[ForgetNameViewController alloc] init];
    vc.vcType = ViewControllerTypeFindName;
//    [self.navigationController pushViewController:vc animated:YES];
   
    IWNavigationController *nav = [[IWNavigationController alloc] initWithRootViewController:vc];
    [IWNavigationController setupWithType:IWNavTypeWhite];
 
         
    //nav.modalTransitionStyle = UIModalTransitionStyleFlipHorizontal;//以屏幕中間x為軸旋轉
    //nav.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;//直接進入頁面,無動畫效果
    nav.modalTransitionStyle = UIModalTransitionStylePartialCurl;//翻頁
   
    [self presentViewController:nav animated:YES completion:nil];
2.自定義的
    1.創建個CATransition動畫
    2.將動畫添加到self.view.window.layer,注意:千萬別忘了window
    3.presentViewController的時候,animated要設置為no
    4.dissmiss的時候,animated也要設置為no,並且,也要添加對應的動畫
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"];
    }];

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM