在最近一个项目中碰到这样一个场景,在被push进来的一个页面设置导航栏透明,且要求控制对tableview组的头视图进行悬停显示,nav随着tableview偏移量改变透明度,当然这样的需求确实不是什么难事,但是如果当前页面继续push一个不需要此类效果的页面,当在返回当前页面的时候就会出现一个坑,nav的展示很突兀,下面是直接上解决方法...ps:假设A页面为需要设置透明,B页面被Apush且不需要设置透明

首先在需要设置导航栏透明的页面的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;
//设置状态栏
[[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent];
//设置标题颜色
self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor clearColor]};
在scrollViewDidScroll代理方法中
-(void)scrollViewDidScroll:(UIScrollView *)scrollView {
CGFloat offset = scrollView.contentOffset.y;
//根据自己需要设置(136)的大小
CGFloat alpha = offset / 136;
_barImageView.alpha = alpha;
//记录下当前的透明度,在返回当前页面时需要
_alpha = alpha;
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithFloat:alpha] forKey:@"_alpha"];
//设置标题的透明度
self.navigationController.navigationBar.titleTextAttributes = @{NSForegroundColorAttributeName : [UIColor colorWithWhite:0 alpha:alpha]};
}
当前页的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的下一个页面需要什么操作呢,我们需要在这个页面显示正常的nav并且禁掉系统的手势pop,自己写一个pop手势,以方便我们拿到pop滑动时的偏移量,在做的时候使用了两个类,在最后会有源码贴出
B.m 须遵守UIGestureRecognizerDelegate,并导入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 {
//记录当前是是否是通过手势滑动回去
[[NSUserDefaults standardUserDefaults] setObject:[NSNumber numberWithBool:YES] forKey:@"isGesturePop"];
/**
* 这里有两个条件不允许手势执行,1、当前控制器为根控制器;2、如果这个push、pop动画正在执行(私有属性)
*/
return self.navigationController.viewControllers.count != 1 && ![[self.navigationController valueForKey:@"_isTransitioning"] boolValue];
}
需要依赖的两个类源码
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手势操作作为一次pop动画的执行
*/
- (void)handleControllerPop:(UIPanGestureRecognizer *)recognizer {
/**
* interactivePopTransition就是我们说的方法2返回的对象,我们需要更新它的进度来控制Pop动画的流程,我们用手指在视图中的位置与视图宽度比例作为它的进度。
*/
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);
/**
* 稳定进度区间,让它在0.0(未完成)~1.0(已完成)之间
*/
progress = MIN(1.0, MAX(0.0, progress));
if (recognizer.state == UIGestureRecognizerStateBegan) {
/**
* 手势开始,新建一个监控对象
*/
self.interactivePopTransition = [[UIPercentDrivenInteractiveTransition alloc] init];
/**
* 告诉控制器开始执行pop的动画
*/
[self.vc popViewControllerAnimated:YES];
}
else if (recognizer.state == UIGestureRecognizerStateChanged) {
/**
* 更新手势的完成进度
*/
[self.interactivePopTransition updateInteractiveTransition:progress];
}
else if (recognizer.state == UIGestureRecognizerStateEnded || recognizer.state == UIGestureRecognizerStateCancelled) {
/**
* 手势结束时如果进度大于一半,那么就完成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中判断如果当前执行的是Pop操作,就返回我们自定义的Pop动画对象。
*/
if (operation == UINavigationControllerOperationPop)
return [[PopAnimation alloc] init];
return nil;
}
- (id<UIViewControllerInteractiveTransitioning>)navigationController:(UINavigationController *)navigationController
interactionControllerForAnimationController:(id<UIViewControllerAnimatedTransitioning>)animationController {
/**
* 方法2会传给你当前的动画对象animationController,判断如果是我们自定义的Pop动画对象,那么就返回interactivePopTransition来监控动画完成度。
*/
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 {
//这个方法返回动画执行的时间
return 0.25;
}
/**
* transitionContext你可以看作是一个工具,用来获取一系列动画执行相关的对象,并且通知系统动画是否完成等功能。
*/
- (void)animateTransition:(id <UIViewControllerContextTransitioning>)transitionContext {
/**
* 获取动画来自的那个控制器
*/
UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
/**
* 获取转场到的那个控制器
*/
UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
/**
* 转场动画是两个控制器视图时间的动画,需要一个containerView来作为一个“舞台”,让动画执行。
*/
UIView *containerView = [transitionContext containerView];
[containerView insertSubview:toViewController.view belowSubview:fromViewController.view];
NSTimeInterval duration = [self transitionDuration:transitionContext];
/**
* 执行动画,我们让fromVC的视图移动到屏幕最右侧
*/
[UIView animateWithDuration:duration animations:^{
fromViewController.view.transform = CGAffineTransformMakeTranslation([UIScreen mainScreen].bounds.size.width, 0);
}completion:^(BOOL finished) {
/**
* 当你的动画执行完成,这个方法必须要调用,否则系统会认为你的其余任何操作都在动画执行过程中。
*/
[transitionContext completeTransition:!transitionContext.transitionWasCancelled];
}];
}
- (void)animationDidStop:(CATransition *)anim finished:(BOOL)flag {
[_transitionContext completeTransition:!_transitionContext.transitionWasCancelled];
}
@end
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
# ios导航栏透明
# ios
# 设置导航栏透明
# ios设置导航栏全透明
# iOS 封装导航栏及返回
# 获取控件所在控制器的实例
# 详解iOS11关于导航栏问题
# 两种iOS隐藏导航栏的正确方法
# iOS App开发中导航栏的创建及基本属性设置教程
# iOS轻松实现导航栏透明渐变
# 简单好用的iOS导航栏封装.runtime属性控制实例代码
# 不需要
# 自定义
# 的是
# 是一个
# 就会
# 偏移量
# 在这个
# 你可以
# 都在
# 这样一个
# 此类
# 作为一个
# 它在
# 等功能
# 来过
# 解决方法
# 用手指
# 写上
# 贴出
# 结束时
相关文章:
婚礼视频制作网站,学习*后期制作的网站有哪些?
制作ppt免费网站有哪些,有哪些比较好的ppt模板下载网站?
个人摄影网站制作流程,摄影爱好者都去什么网站?
,石家庄四十八中学官网?
实例解析Array和String方法
宝塔建站无法访问?如何排查配置与端口问题?
如何在Golang中使用encoding/gob序列化对象_存储和传输数据
潍坊网站制作公司有哪些,潍坊哪家招聘网站好?
python的本地网站制作,如何创建本地站点?
建站为何优先选择香港服务器?
建站之星如何优化SEO以实现高效排名?
如何快速搭建自助建站会员专属系统?
如何做网站制作流程,*游戏网站怎么搭建?
微信小程序 五星评分(包括半颗星评分)实例代码
武汉外贸网站制作公司,现在武汉外贸前景怎么样啊?
高防服务器租用首荐平台,企业级优惠套餐快速部署
高防服务器如何保障网站安全无虞?
如何在Windows虚拟主机上快速搭建网站?
如何制作网站标识牌,动态网站如何制作(教程)?
建站主机如何选?高性价比方案全解析
如何在万网开始建站?分步指南解析
建站主机类型有哪些?如何正确选型
整蛊网站制作软件,手机不停的收到各种网站的验证码短信,是手机病毒还是人为恶搞?有这种手机病毒吗?
,南京靠谱的征婚网站?
如何选择建站程序?包含哪些必备功能与类型?
网站建设制作、微信公众号,公明人民医院怎么在网上预约?
网站制作网站,深圳做网站哪家比较好?
中山网站推广排名,中山信息港登录入口?
建站之星后台密码如何安全设置与找回?
建站OpenVZ教程与优化策略:配置指南与性能提升
建站之星备案是否影响网站上线时间?
商务网站制作工程师,从哪几个方面把握电子商务网站主页和页面的特色设计?
建站之星官网登录失败?如何快速解决?
如何自己制作一个网站链接,如何制作一个企业网站,建设网站的基本步骤有哪些?
如何在Ubuntu系统下快速搭建WordPress个人网站?
制作网站建设的公司有哪些,网站建设比较好的公司都有哪些?
怎么将XML数据可视化 D3.js加载XML
如何在阿里云ECS服务器部署织梦CMS网站?
手机钓鱼网站怎么制作视频,怎样拦截钓鱼网站。怎么办?
广州顶尖建站服务:企业官网建设与SEO优化一体化方案
无锡营销型网站制作公司,无锡网选车牌流程?
,网站推广常用方法?
天河区网站制作公司,广州天河区如何办理身份证?需要什么资料有预约的网站吗?
网站制作中优化长尾关键字挖掘的技巧,建一个视频网站需要多少钱?
建站之星五站合一营销型网站搭建攻略,流量入口全覆盖优化指南
制作电商网页,电商供应链怎么做?
大连网站设计制作招聘信息,大连投诉网站有哪些?
油猴 教程,油猴搜脚本为什么会网页无法显示?
南宁网站建设制作定制,南宁网站建设可以定制吗?
制作充值网站的软件,做人力招聘为什么要自己交端口钱?
*请认真填写需求信息,我们会在24小时内与您取得联系。