iOS實(shí)現(xiàn)導(dǎo)航欄透明示例代碼
在最近一個(gè)項(xiàng)目中碰到這樣一個(gè)場(chǎng)景,在被push進(jìn)來(lái)的一個(gè)頁(yè)面設(shè)置導(dǎo)航欄透明,且要求控制對(duì)tableview組的頭視圖進(jìn)行懸停顯示,nav隨著tableview偏移量改變透明度,當(dāng)然這樣的需求確實(shí)不是什么難事,但是如果當(dāng)前頁(yè)面繼續(xù)push一個(gè)不需要此類效果的頁(yè)面,當(dāng)在返回當(dāng)前頁(yè)面的時(shí)候就會(huì)出現(xiàn)一個(gè)坑,nav的展示很突兀,下面是直接上解決方法...ps:假設(shè)A頁(yè)面為需要設(shè)置透明,B頁(yè)面被Apush且不需要設(shè)置透明
首先在需要設(shè)置導(dǎo)航欄透明的頁(yè)面的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)前頁(yè)面時(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)前頁(yè)的viewWillAppear, viewDidAppear, viewWillDisappear
-(void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; self.table.delegate = self; } -(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è)頁(yè)面需要什么操作呢,我們需要在這個(gè)頁(yè)面顯示正常的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就是我們說(shuō)的方法2返回的對(duì)象,我們需要更新它的進(jìn)度來(lái)控制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操作,否則重新來(lái)過。 */ 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來(lái)監(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è)工具,用來(lái)獲取一系列動(dòng)畫執(zhí)行相關(guān)的對(duì)象,并且通知系統(tǒng)動(dòng)畫是否完成等功能。 */ - (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext { /** * 獲取動(dòng)畫來(lái)自的那個(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來(lái)作為一個(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
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS中的音頻服務(wù)和音頻AVAudioPlayer音頻播放器使用指南
這里我們要介紹的是AVAudio ToolBox框架中的AudioServicesPlaySystemSound函數(shù)創(chuàng)建的服務(wù),特別適合用來(lái)制作鈴聲,下面就簡(jiǎn)單整理一下iOS中的音頻服務(wù)和音頻AVAudioPlayer音頻播放器使用指南:2016-06-06iOS開發(fā)之級(jí)聯(lián)界面(推薦界面)搭建原理
這篇文章主要為大家詳細(xì)介紹了iOS級(jí)聯(lián)界面(推薦界面)搭建原理,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-08-08舉例講解Objective-C中@property屬性的用法
這篇文章主要介紹了Objective-C中@property屬性的用法,包括@property的屬性關(guān)鍵字的整理,需要的朋友可以參考下2016-03-03objc方法聲明和實(shí)現(xiàn)由于參數(shù)類型不一致所引發(fā)的崩潰
這篇文章主要為大家介紹了objc方法聲明和實(shí)現(xiàn)由于參數(shù)類型不一致所引發(fā)的崩潰詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-03-03iOS swift 總結(jié)NavigationController出現(xiàn)問題及解決方法
這篇文章主要介紹了iOS swift 總結(jié)NavigationController出現(xiàn)問題及解決方法的相關(guān)資料,需要的朋友可以參考下2016-12-12IOS實(shí)現(xiàn)簡(jiǎn)單的進(jìn)度條功能
這篇文章主要介紹了IOS實(shí)現(xiàn)簡(jiǎn)單的進(jìn)度條功能的相關(guān)資料,需要的朋友可以參考下2016-01-01詳解Objective-C編程中對(duì)設(shè)計(jì)模式中適的配器模式的使用
這篇文章主要介紹了Objective-C編程中對(duì)設(shè)計(jì)模式中適的配器模式的使用,適配器模式中的Adapter適配器允許接口不兼容的類在一起工作,需要的朋友可以參考下2016-03-03iOS動(dòng)畫實(shí)現(xiàn)雨花與櫻花特效
小編今天為大家?guī)?lái)一場(chǎng)淅淅瀝瀝的夜空之雨和滿天飛舞的櫻花之戀,希望能在炎炎夏日為您帶來(lái)一絲清爽的涼意!學(xué)習(xí)iOS動(dòng)畫的小伙伴們可以參考學(xué)習(xí)。2016-08-08