iOS 導(dǎo)航欄透明

在最近一個(gè)項(xiàng)目中碰到這樣一個(gè)場(chǎng)景,在被push進(jìn)來的一個(gè)頁面設(shè)置導(dǎo)航欄透明,且要求控制對(duì)tableview組的頭視圖進(jìn)行懸停顯示,nav隨著tableview偏移量改變透明度,當(dāng)然這樣的需求確實(shí)不是什么難事,但是如果當(dāng)前頁面繼續(xù)push一個(gè)不需要此類效果的頁面,當(dāng)在返回當(dāng)前頁面的時(shí)候就會(huì)出現(xiàn)一個(gè)坑,nav的展示很突兀,下面是直接上解決方法...ps:假設(shè)A頁面為需要設(shè)置透明,B頁面被Apush且不需要設(shè)置透明

A.m

首先在需要設(shè)置導(dǎo)航欄透明的頁面的viewDidload中寫上

self.title = @"Title";
[self.navigationController.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    self.navigationController.navigationBar.shadowImage = [UIImage new];
    self.barImageView = self.navigationController.navigationBar.subviews.firstObject;
    self.barImageView.alpha = 0;
    //設(shè)置狀態(tài)欄
    [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
    //設(shè)置標(biāo)題顏色
    self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor clearColor]};
   

在scrollViewDidScroll代理方法中

-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
 
    CGFloat offset = scrollView.contentOffset.y;
    //根據(jù)自己需要設(shè)置(136)的大小
    CGFloat alpha = offset / 136;
    _barImageView.alpha = alpha;
    //記錄下當(dāng)前的透明度,在返回當(dāng)前頁面時(shí)需要
    _alpha = alpha;
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:alpha] forKey:@"_alpha"];
    //設(shè)置標(biāo)題的透明度
    self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor colorWithWhite:0 alpha:alpha]};
}

當(dāng)前頁的viewWillAppear, viewDidAppear, viewWillDisappear

-(void)viewWillAppear:(BOOL)animated
{
    
    [super viewWillAppear:animated];
    self.table.delegate = self;

   BOOL isGesturePop = [[[NSUserDefaults standardUserDefaults] objectForKey:@"isGesturePop"] boolValue];
    self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor colorWithWhite:0 alpha:_alpha]};
    if (!isGesturePop) {
        [UIView animateWithDuration:0.25 animations:^{
            _barImageView.alpha = _alpha;
            self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor colorWithWhite:0 alpha:_alpha]};
        }];
    }
}

-(void)viewDidAppear:(BOOL)animated {
    //BOOL isGesturePop = [[[NSUserDefaults standardUserDefaults] objectForKey:@"isGesturePop"] boolValue];
//    if (!isGesturePop) {
   //     _barImageView.alpha = _alpha;
      //  self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor colorWithWhite:0 alpha:_alpha]};
    //}
    [super viewDidAppear:animated];
}

-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    self.table.delegate = nil;
    self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor blackColor]};
    
    _barImageView.alpha = 1;
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:NO] forKey:@"isGesturePop"];
}

那么在我們需要push的下一個(gè)頁面需要什么操作呢,我們需要在這個(gè)頁面顯示正常的nav并且禁掉系統(tǒng)的手勢(shì)pop,自己寫一個(gè)pop手勢(shì),以方便我們拿到pop滑動(dòng)時(shí)的偏移量,在做的時(shí)候使用了兩個(gè)類,在最后會(huì)有源碼貼出

B.m 須遵守UIGestureRecognizerDelegate,并導(dǎo)入NavigationInteractiveTransition.h

全局變量

@property (nonatomic, strong) NavigationInteractiveTransition *navT;

viewDidLoad

self.navigationController.interactivePopGestureRecognizer.enabled = NO;
    
    UIGestureRecognizer *gesture = self.navigationController.interactivePopGestureRecognizer;
    gesture.enabled = NO;
    UIView *gestureView = gesture.view;
    
    UIPanGestureRecognizer *popRecognizer = [[UIPanGestureRecognizer alloc] init];
    popRecognizer.delegate = self;
    popRecognizer.maximumNumberOfTouches = 1;
    [gestureView addGestureRecognizer:popRecognizer];
    
    _navT = [[NavigationInteractiveTransition alloc] initWithViewController:self.navigationController];
    [popRecognizer addTarget:_navT action:@selector(handleControllerPop:)];

UIGestureRecognizerDelegate 代理方法gestureRecognizerShouldBegin

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer {
    //記錄當(dāng)前是是否是通過手勢(shì)滑動(dòng)回去
    [[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"isGesturePop"];
    /**
     *  這里有兩個(gè)條件不允許手勢(shì)執(zhí)行,1、當(dāng)前控制器為根控制器;2、如果這個(gè)push、pop動(dòng)畫正在執(zhí)行(私有屬性)
     */
    return self.navigationController.viewControllers.count != 1 && ![[self.navigationController valueForKey:@"_isTransitioning"] boolValue];
}

需要依賴的兩個(gè)類源碼

NavigationInteractiveTransition.h

#import <UIKit/UIKit.h>

@class UIViewController, UIPercentDrivenInteractiveTransition;
@interface NavigationInteractiveTransition : NSObject <UINavigationControllerDelegate>
- (instancetype)initWithViewController:(UIViewController *)vc;
- (void)handleControllerPop:(UIPanGestureRecognizer *)recognizer;
- (UIPercentDrivenInteractiveTransition *)interactivePopTransition;
@end

NavigationInteractiveTransition.m

#import "NavigationInteractiveTransition.h"
#import "PopAnimation.h"

@interface NavigationInteractiveTransition ()
@property (nonatomic, weak) UINavigationController *vc;
@property (nonatomic, strong) UIPercentDrivenInteractiveTransition *interactivePopTransition;
@property(nonatomic, strong) UIImageView *barImageView;
@end

@implementation NavigationInteractiveTransition

- (instancetype)initWithViewController:(UIViewController *)vc
{
    self = [super init];
    if (self) {
        self.vc = (UINavigationController *)vc;
        self.vc.delegate = self;
    }
    return self;
}

/**
 *  我們把用戶的每次Pan手勢(shì)操作作為一次pop動(dòng)畫的執(zhí)行
 */
- (void)handleControllerPop:(UIPanGestureRecognizer *)recognizer {
    /**
     *  interactivePopTransition就是我們說的方法2返回的對(duì)象,我們需要更新它的進(jìn)度來控制Pop動(dòng)畫的流程,我們用手指在視圖中的位置與視圖寬度比例作為它的進(jìn)度。
     */
    CGFloat progress = [recognizer translationInView:recognizer.view].x / recognizer.view.bounds.size.width;
    [self.vc.navigationBar setBackgroundImage:[UIImage new] forBarMetrics:UIBarMetricsDefault];
    self.vc.navigationBar.shadowImage = [UIImage new];
    self.barImageView = self.vc.navigationBar.subviews.firstObject;
    
    CGFloat alpha = [[[NSUserDefaults standardUserDefaults] objectForKey:@"_alpha"] floatValue];
    self.barImageView.alpha = 1 - progress > alpha ? alpha : 1 - progress;
//    NSLog(@"===progress==%.2f",progress);
    /**
     *  穩(wěn)定進(jìn)度區(qū)間,讓它在0.0(未完成)~1.0(已完成)之間
     */
    progress = MIN(1.0, MAX(0.0, progress));
    if (recognizer.state == UIGestureRecognizerStateBegan) {
        /**
         *  手勢(shì)開始,新建一個(gè)監(jiān)控對(duì)象
         */
        self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
        /**
         *  告訴控制器開始執(zhí)行pop的動(dòng)畫
         */
        [self.vc popViewControllerAnimated:YES];
    }
    else if (recognizer.state == UIGestureRecognizerStateChanged) {
        
        /**
         *  更新手勢(shì)的完成進(jìn)度
         */
        [self.interactivePopTransition updateInteractiveTransition:progress];
    }
    else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
        
        /**
         *  手勢(shì)結(jié)束時(shí)如果進(jìn)度大于一半,那么就完成pop操作,否則重新來過。
         */
        if (progress > 0.5) {
            [self.interactivePopTransition finishInteractiveTransition];
            self.barImageView.alpha = 0;;
        }
        else {
            [self.interactivePopTransition cancelInteractiveTransition];
        }

        self.interactivePopTransition = nil;
    }
    
}

- (id<UIViewControllerAnimatedTransitioning>)navigationController:(UINavigationController *)navigationController
                                  animationControllerForOperation:(UINavigationControllerOperation)operation
                                               fromViewController:(UIViewController *)fromVC
                                                 toViewController:(UIViewController *)toVC {
    /**
     *  方法1中判斷如果當(dāng)前執(zhí)行的是Pop操作,就返回我們自定義的Pop動(dòng)畫對(duì)象。
     */
    if (operation == UINavigationControllerOperationPop)
        return [[PopAnimation alloc] init];

    return nil;
}

- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
                         interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {

    /**
     *  方法2會(huì)傳給你當(dāng)前的動(dòng)畫對(duì)象animationController,判斷如果是我們自定義的Pop動(dòng)畫對(duì)象,那么就返回interactivePopTransition來監(jiān)控動(dòng)畫完成度。
     */
    if ([animationController isKindOfClass:[PopAnimation class]])
        return self.interactivePopTransition;

    return nil;
}

@end

PopAnimation.h

#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>

@interface PopAnimation : NSObject <UIViewControllerAnimatedTransitioning>

@end

PopAnimation.m

#import "PopAnimation.h"

@interface PopAnimation ()
@property (nonatomic, strong) id <UIViewControllerContextTransitioning> transitionContext;
@end

@implementation PopAnimation

- (NSTimeInterval)transitionDuration:(id <UIViewControllerContextTransitioning>)transitionContext {
    //這個(gè)方法返回動(dòng)畫執(zhí)行的時(shí)間
    return 0.25;
}

/**
 *  transitionContext你可以看作是一個(gè)工具,用來獲取一系列動(dòng)畫執(zhí)行相關(guān)的對(duì)象,并且通知系統(tǒng)動(dòng)畫是否完成等功能。
 */
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
    /**
     *  獲取動(dòng)畫來自的那個(gè)控制器
     */
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    /**
     *  獲取轉(zhuǎn)場(chǎng)到的那個(gè)控制器
     */
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    
    /**
     *  轉(zhuǎn)場(chǎng)動(dòng)畫是兩個(gè)控制器視圖時(shí)間的動(dòng)畫,需要一個(gè)containerView來作為一個(gè)“舞臺(tái)”,讓動(dòng)畫執(zhí)行。
     */
    UIView *containerView = [transitionContext containerView];
    [containerView insertSubview:toViewController.view belowSubview:fromViewController.view];
    
    NSTimeInterval duration = [self transitionDuration:transitionContext];

    /**
     *  執(zhí)行動(dòng)畫,我們讓fromVC的視圖移動(dòng)到屏幕最右側(cè)
     */
    [UIView animateWithDuration:duration animations:^{
        fromViewController.view.transform = CGAffineTransformMakeTranslation([UIScreen mainScreen].bounds.size.width, 0);
    }completion:^(BOOL finished) {
        /**
         *  當(dāng)你的動(dòng)畫執(zhí)行完成,這個(gè)方法必須要調(diào)用,否則系統(tǒng)會(huì)認(rèn)為你的其余任何操作都在動(dòng)畫執(zhí)行過程中。
         */
        [transitionContext completeTransition:!transitionContext.transitionWasCancelled];
    }];

}

- (void)animationDidStop:(CATransition *)anim finished:(BOOL)flag {
    [_transitionContext completeTransition:!_transitionContext.transitionWasCancelled];
}
@end

ps:如果是自定義view設(shè)置nav或者是直接隱藏nav可以參考我的另一篇簡(jiǎn)書http://www.lxweimin.com/p/b46166b05f02
備注:還有些許不足請(qǐng)各位見諒指正

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,967評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,273評(píng)論 3 415
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,870評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,742評(píng)論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,527評(píng)論 6 407
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,010評(píng)論 1 322
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,108評(píng)論 3 440
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,250評(píng)論 0 288
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,769評(píng)論 1 333
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,656評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,853評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,371評(píng)論 5 358
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,103評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,472評(píng)論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,717評(píng)論 1 281
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,487評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,815評(píng)論 2 372

推薦閱讀更多精彩內(nèi)容

  • 在寫透明導(dǎo)航欄的時(shí)候,如果沒有側(cè)滑手勢(shì)pop控制器倒是一件簡(jiǎn)單的事。如我之前的項(xiàng)目一樣,直接設(shè)置就行了,也不應(yīng)考慮...
    損失了成噸智商的小海Jy閱讀 4,296評(píng)論 0 6
  • 最近碰到項(xiàng)目需求是一個(gè)導(dǎo)航欄多種樣式的處理 而且有些頁面還需要漸變效果 沒辦法看了很多demo 還是沒有符合需求的...
    Alife丶閱讀 1,367評(píng)論 1 4
  • 開發(fā)過程中,會(huì)遇到導(dǎo)航欄透明問題。如下圖的需求: 要實(shí)現(xiàn)這個(gè)效果要注意到的點(diǎn): 1、系統(tǒng)有提供隱藏導(dǎo)航欄的方法 o...
    槑槑鶴閱讀 1,245評(píng)論 1 8
  • 像這樣的效果,navigationController.navigationBar變?yōu)橥该鳎瑫r(shí)又不影響返回等按鈕...
    黑色桃芯閱讀 434評(píng)論 0 3
  • 功能需求:根新浪微博個(gè)人主頁類似,下拉拉伸放大圖片下拉刷新(前面文章已解決),向上滑動(dòng)的時(shí)候,導(dǎo)航欄的透明度逐漸增...
    啓蘊(yùn)閱讀 700評(píng)論 1 2