iOS透明导航栏的平滑过渡(进阶版)

本文详细介绍了如何实现iOS应用中透明导航栏在切换界面时的平滑过渡,包括设置导航栏透明度、为UIViewController添加导航栏透明度属性,以及实现渐变过渡效果。通过Category和Runtime技术,避免了导航栏切换时的生硬动画,提供了类似QQ应用的优秀用户体验。同时,文章还修复了一些小瑕疵,确保在不同场景下导航栏过渡的流畅性。
摘要由CSDN通过智能技术生成

如我在传送门:iOS导航栏切换界面时隐藏和显示中所说,现在很多App的个人中心模块都是不保留导航栏的,会直接使导航栏透明,比如做的很好的QQ个人信息界面:

为什么说QQ做的很好呢?既然有透明的导航栏也有不透明的导航栏,那一定会在界面切换之间存在一个过渡的过程,而这个过程,QQ做的特别好,在从透明导航栏界面返回到不透明导航栏界面时,导航栏的透明度是一个渐进的过渡效果,甚至会有一种毛玻璃的效果,感兴趣的可以打开手机QQ到个人界面看一看,效果很赞。

而很多App的做法其实比较粗糙,类似于我在传送门:iOS导航栏切换界面时隐藏和显示中的做法,需要导航栏透明时,直接将导航栏隐藏起来。直接隐藏起来的意思是,整个导航栏就用不了了,也就是说,标题、返回按钮等都需要自己去做,这是一个比较麻烦的地方,此外,在有无导航栏的界面间切换时,过程是比较生硬的,导航栏不是渐变出现的。如果说这些都可以接受,那最大的一个问题,也是我在那篇文章里提到的,如果正好处于用UITabbarConatroller切换界面,那么导航栏会有一个往上缩回的快速动画,这其实就很不美观了,当然我们可以通过将隐藏导航栏的动画去掉来达到对Tabbar切换友好的效果:

[self.navigationController setNavigationBarHidden:NO animated:NO];

但是这样一来你在UINavigationController体系下切换界面时由于没有了动画,这边的效果又会变得很差。这两个矛盾没有想到可以调和的手段,除非在业务上就不显示Tabbar了,但始终不是长久之计。

同时,我们虽然说QQ做的很好,但也依然有一些不足,多把玩一下导航栏过渡的过程就会发现,如果准备从透明导航栏返回时又决定不反回了,还是停留在导航栏透明的界面,这时候导航栏虽然会回到透明,但会有一个导航栏闪现一下的小瑕疵。

现在问题已经讲完了,基于这些问题,我们自己来尝试实现一种更好的平滑过渡效果,不自定义导航栏,直接利用系统原生的导航栏,使用Category和Runtime的技术,达到这个效果:

代码可以在示例工程下载(觉得有帮助的小伙伴请不吝加Star~):https://github.com/Cloudox/SmoothNavDemo

实现过程

其实我们的目的总结起来有三个:

1、不去自定义导航栏,就用系统原生的,标题、返回按钮啥的都方便加,这也就是说不隐藏导航栏,而是要单独让导航栏背景透明;
2、在导航栏透明与否的界面间切换时透明度有渐变效果;
3、在UINavigationController体系和UITabarController体系下切换界面都很完美。

对于第三个目的,我们之前在UITabarController下切换时会有导航栏隐藏的小动画,但如果我们满足了第一个目的,那就不存在隐藏导航栏了,所以第三个问题也就不会存在了。

我们先来看第一个目的。

设置导航栏背景透明度

导航栏上应该是有很多view的,我们要做的是只让背景透明,而保留标题、返回按钮。iOS没有直接给我们提供对于导航栏背景view的访问途径,那么我们只能自己来找了。

首先我们遍历打印出UINavigationBar的所有子视图,是所有,包括子视图的一层层子视图,来看看到底导航栏都包含了哪些东西:

上面这张图就是导航栏UINavigationBar所包含的所有子view了,序号和缩进表示了其层级归属关系,打印的方法可以看这篇文章:传送门:iOS遍历打印所有子视图

从这些子view的类名能够大概猜出他们都是导航栏上的什么,让我们大胆猜测一下,_UIBarBackground 是背景视图,下属的 UIImageView 是背景图片,_UINavigationBarBackIndicatorView 是返回箭头,UINavigationItemView 是添加的一些导航栏按钮,包括返回按钮,因为我没有给导航栏添加任何其他按钮,所以这里一定是返回按钮,下属的 UILabel 就是 “返回” 两个字了。

根据上面得到的信息,我们就尝试将_UIBarBackground、UIImageView、UIVisualEffectView的 alpha 值设为 1 或者 0 来改变导航栏背景的透明度。

我们可以给 UINavigationController 创建一个类别,来给这个类添加一个方法,用于设置导航栏的透明度:

// UIViewController+Cloudox.m

- (void)setNeedsNavigationBackground:(CGFloat)alpha {
    // 导航栏背景透明度设置
    UIView *barBackgroundView = [[self.navigationBar subviews] objectAtIndex:0];// _UIBarBackground
    UIImageView *backg
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值