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è)不需要此類(lèi)效果的頁(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中寫(xiě)上
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,自己寫(xiě)一個(gè)pop手勢(shì),以方便我們拿到pop滑動(dòng)時(shí)的偏移量,在做的時(shí)候使用了兩個(gè)類(lèi),在最后會(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)前是是否是通過(guò)手勢(shì)滑動(dòng)回去
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"isGesturePop"];
/**
* 這里有兩個(gè)條件不允許手勢(shì)執(zhí)行,1、當(dāng)前控制器為根控制器;2、如果這個(gè)push、pop動(dòng)畫(huà)正在執(zhí)行(私有屬性)
*/
return self.navigationController.viewControllers.count != 1 && ![[self.navigationController valueForKey:@"_isTransitioning"] boolValue];
}
需要依賴(lài)的兩個(gè)類(lèi)源碼
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;
}
/**
* 我們把用戶(hù)的每次Pan手勢(shì)操作作為一次pop動(dòng)畫(huà)的執(zhí)行
*/
- (void)handleControllerPop:(UIPanGestureRecognizer *)recognizer {
/**
* interactivePopTransition就是我們說(shuō)的方法2返回的對(duì)象,我們需要更新它的進(jìn)度來(lái)控制Pop動(dòng)畫(huà)的流程,我們用手指在視圖中的位置與視圖寬度比例作為它的進(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ì)開(kāi)始,新建一個(gè)監(jiān)控對(duì)象
*/
self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
/**
* 告訴控制器開(kāi)始執(zhí)行pop的動(dòng)畫(huà)
*/
[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)過(guò)。
*/
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)畫(huà)對(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)畫(huà)對(duì)象animationController,判斷如果是我們自定義的Pop動(dòng)畫(huà)對(duì)象,那么就返回interactivePopTransition來(lái)監(jiān)控動(dòng)畫(huà)完成度。
*/
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)畫(huà)執(zhí)行的時(shí)間
return 0.25;
}
/**
* transitionContext你可以看作是一個(gè)工具,用來(lái)獲取一系列動(dòng)畫(huà)執(zhí)行相關(guān)的對(duì)象,并且通知系統(tǒng)動(dòng)畫(huà)是否完成等功能。
*/
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
/**
* 獲取動(dòng)畫(huà)來(lái)自的那個(gè)控制器
*/
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
/**
* 獲取轉(zhuǎn)場(chǎng)到的那個(gè)控制器
*/
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
/**
* 轉(zhuǎn)場(chǎng)動(dòng)畫(huà)是兩個(gè)控制器視圖時(shí)間的動(dòng)畫(huà),需要一個(gè)containerView來(lái)作為一個(gè)“舞臺(tái)”,讓動(dòng)畫(huà)執(zhí)行。
*/
UIView *containerView = [transitionContext containerView];
[containerView insertSubview:toViewController.view belowSubview:fromViewController.view];
NSTimeInterval duration = [self transitionDuration:transitionContext];
/**
* 執(zhí)行動(dòng)畫(huà),我們讓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)畫(huà)執(zhí)行完成,這個(gè)方法必須要調(diào)用,否則系統(tǒng)會(huì)認(rèn)為你的其余任何操作都在動(dòng)畫(huà)執(zhí)行過(guò)程中。
*/
[transitionContext completeTransition:!transitionContext.transitionWasCancelled];
}];
}
- (void)animationDidStop:(CATransition *)anim finished:(BOOL)flag {
[_transitionContext completeTransition:!_transitionContext.transitionWasCancelled];
}
@end
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
Xcode 9下適配iPhoneX導(dǎo)致iOS 10不兼容問(wèn)題的解決方法
這篇文章主要給大家介紹了關(guān)于Xcode 9下適配iPhoneX導(dǎo)致iOS 10不兼容問(wèn)題的解決方法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-04-04
UIImage加載圖片Images.xcassets加載方法的影響
這篇文章主要介紹了UIImage加載圖片Images.xcassets加載方法的影響的相關(guān)資料,需要的朋友可以參考下2016-12-12
總結(jié)iOS App開(kāi)發(fā)中控制屏幕旋轉(zhuǎn)的幾種方式
這篇文章主要介紹了iOS app開(kāi)發(fā)中控制屏幕旋轉(zhuǎn)的方法總結(jié),分為自動(dòng)旋轉(zhuǎn)和手動(dòng)旋轉(zhuǎn)以及強(qiáng)制旋轉(zhuǎn)三種情況,代碼為Objective-C語(yǔ)言,需要的朋友可以參考下2016-02-02
IOS開(kāi)發(fā)網(wǎng)絡(luò)篇—Socket編程詳解
這篇文章主要介紹了IOS開(kāi)發(fā)網(wǎng)絡(luò)篇—Socket編程的相關(guān)資料,需要的朋友可以參考下2016-09-09
iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例
這篇文章主要介紹了iOS WKWebview 白屏檢測(cè)實(shí)現(xiàn)的示例,幫助大家更好的進(jìn)行ios開(kāi)發(fā),感興趣的朋友可以了解下2020-10-10
IOS 改變導(dǎo)航欄返回按鈕的標(biāo)題實(shí)例詳解
這篇文章主要介紹了IOS 改變導(dǎo)航欄返回按鈕的標(biāo)題實(shí)例詳解的相關(guān)資料,需要的朋友可以參考下2017-04-04
iOS App開(kāi)發(fā)中使用設(shè)計(jì)模式中的單例模式的實(shí)例解析
單例模式是最簡(jiǎn)單和基本的一種設(shè)計(jì)模式,下面我們就簡(jiǎn)單解讀一下iOS中單例設(shè)計(jì)模式的用法,示例代碼還是為傳統(tǒng)的Objective-C,主要為了體現(xiàn)單例模式的思想,需要的朋友可以參考下2016-05-05

