gpt4 book ai didi

iOS实现导航栏透明示例代码

转载 作者:qq735679552 更新时间:2022-09-27 22:32:09 26 4
gpt4 key购买 nike

CFSDN坚持开源创造价值,我们致力于搭建一个资源共享平台,让每一个IT人在这里找到属于你的精彩世界.

这篇CFSDN的博客文章iOS实现导航栏透明示例代码由作者收集整理,如果你对这篇文章有兴趣,记得点赞哟.

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

首先在需要设置导航栏透明的页面的viewDidload中写上 。

?
1
2
3
4
5
6
7
8
9
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代理方法中 。

?
1
2
3
4
5
6
7
8
9
10
11
12
-( 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 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
-( 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 。

全局变量 。

?
1
@property (nonatomic, strong) NavigationInteractiveTransition *navT;

viewDidLoad 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
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 。

?
1
2
3
4
5
6
7
8
- ( 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 。

?
1
2
3
4
5
6
7
8
#import <UIKit/UIKit.h>
 
@ class UIViewController, UIPercentDrivenInteractiveTransition;
@interface NavigationInteractiveTransition : NSObject <UINavigationControllerDelegate>
- (instancetype)initWithViewController:(UIViewController *)vc;
- ( void )handleControllerPop:(UIPanGestureRecognizer *)recognizer;
- (UIPercentDrivenInteractiveTransition *)interactivePopTransition;
@end

NavigationInteractiveTransition.m 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
#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 。

?
1
2
3
4
5
6
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
 
@interface PopAnimation : NSObject <UIViewControllerAnimatedTransitioning>
 
@end

PopAnimation.m 。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#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

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我.

原文链接:http://www.jianshu.com/p/1e4d342ef7ac 。

最后此篇关于iOS实现导航栏透明示例代码的文章就讲到这里了,如果你想了解更多关于iOS实现导航栏透明示例代码的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com