UINavigationBar 是每一個(gè) iOS 工程師都會(huì)遇到的坎括享,它令人抓狂的地方在于是否能隨著頁(yè)面切換而平滑地過(guò)渡到目的狀態(tài)苍息。想要把這件事情做好窿凤,不需要高深的算法勺拣,不需要深刻的底層原理屈藐,只需要一顆執(zhí)著的內(nèi)心榔组。
介紹
我們來(lái)看微信是如何平滑切換導(dǎo)航欄的狀態(tài)的
我 頁(yè)面和 收藏 頁(yè)面的導(dǎo)航欄具有不同的 barStyle 以及背景色
當(dāng)從 收藏 右滑返回 我 頁(yè)面時(shí),NavigationBar 的背景被分成黑白兩段联逻,并且 bar 上的元素平滑切換搓扯,就和只有一個(gè)背景色時(shí)一樣。
仔細(xì)觀察包归,我 頁(yè)面和 收藏 頁(yè)面的導(dǎo)航欄背景顏色不一樣锨推,但是都有毛玻璃效果
收藏 頁(yè)面往上滑動(dòng)到一定程度時(shí),導(dǎo)航欄會(huì)出現(xiàn) shadowImage公壤,此時(shí)如果右滑返回换可,導(dǎo)航欄依然在 收藏 頁(yè)保留 shadowImage,然而 我 頁(yè)面卻沒(méi)有這根線
不得不說(shuō)厦幅,細(xì)節(jié)處理得真好
下面沾鳄,我們來(lái)看一個(gè)反例,這是掘金 app 收藏頁(yè)面的效果确憨,當(dāng)右滑返回上一個(gè)頁(yè)面時(shí)译荞,導(dǎo)航欄那反應(yīng)實(shí)在是突兀,尖銳休弃。
特別說(shuō)明吞歼,本人舉掘金這個(gè)例子,純粹是因?yàn)榫蚪鹗潜救顺S?app 之一
導(dǎo)航欄的平滑過(guò)渡玫芦,可以劃分為以下情況
陰影隱與現(xiàn)
以下展示了平滑切換 shadowImage 的隱與現(xiàn)
導(dǎo)航欄有與無(wú)
以下展示導(dǎo)航欄有與無(wú)之間的平滑切換浆熔,和調(diào)用 setNavigationBarHidden:animated:
的效果不一樣哦
導(dǎo)航欄背景透與暗
這種效果是不是比掘金好多了
導(dǎo)航欄背景不同
看下面效果,導(dǎo)航欄背景的表現(xiàn)是不是和微信一樣
Usage
上面這些效果是三個(gè)類(lèi)共同協(xié)作的結(jié)果桥帆,總共約 400 行代碼
HBDNavigationBar 繼承 UINavigationBar
HBDNavigationController 繼承 UINavigationController医增, 內(nèi)部使用了 HBDNavigationBar
UIViewController(HBD) 是個(gè)分類(lèi),里面有一些可配置屬性
@property (nonatomic, assign) UIBarStyle hbd_barStyle; // 導(dǎo)航欄樣式
@property (nonatomic, strong) UIColor *hbd_barTintColor; // 導(dǎo)航欄背景顏色
@property (nonatomic, assign) float hbd_barAlpha; // 導(dǎo)航欄背景透明度
@property (nonatomic, assign) BOOL hbd_barHidden; // 是否隱藏導(dǎo)航欄
@property (nonatomic, assign, readonly) float hbd_barShadowAlpha; // 只讀老虫,通過(guò)其它屬性計(jì)算出來(lái)
@property (nonatomic, assign) BOOL hbd_barShadowHidden; // 是否隱藏導(dǎo)航欄下面的陰影
@property (nonatomic, assign) BOOL hbd_backInteractive; // 當(dāng)前頁(yè)面是否響應(yīng)右滑返回叶骨,默認(rèn)是 YES
實(shí)際使用起來(lái)很簡(jiǎn)單
// HBDNavigationController 只有在創(chuàng)建 UINavigationController 時(shí)使用到
// HBDNavigationBar 只有在使用 storyboard 時(shí)才有機(jī)會(huì)登場(chǎng)
DemoViewController *vc = [[DemoViewController alloc] init];
self.window.rootViewController = [[HBDNavigationController alloc] initWithRootViewController:vc];
在 viewDidLoad 中通過(guò)分類(lèi)配置想要的效果即可
@implementation DemoViewController
- (void)viewDidLoad {
[super viewDidLoad];
// 隱藏導(dǎo)航欄,就這樣祈匙,不需要調(diào)用 setNavigationBarHidden:animated:
// 也不需要擔(dān)心其它頁(yè)面會(huì)受到影響
self.hbd_barHidden = YES;
}
@end
注意事項(xiàng)以及限制
hbd_barHidden
并不真正隱藏導(dǎo)航欄忽刽,只是把它變透明了天揖,當(dāng)然事件是可以穿透的,也正因?yàn)椴⒉徽嬲[藏導(dǎo)航欄跪帝,才可以在導(dǎo)航欄有無(wú)之間平滑而優(yōu)雅地切換
只支持通過(guò) hbd_barTintColor
設(shè)置背景顏色今膊,不支持設(shè)置背景圖片,也就是說(shuō)伞剑,調(diào)用 setBackgroundImage:forBarMetrics:
是無(wú)效的
如果需要毛玻璃效果焙蹭,那么設(shè)置給 hbd_barTintColor
的值應(yīng)該帶有透明度添忘,具體數(shù)值根據(jù)色值的不同而不同。不要通過(guò) hbd_barAlpha
來(lái)調(diào)整毛玻璃效果箩艺,它是用來(lái)動(dòng)態(tài)控制導(dǎo)航欄背景的透與暗的亩歹,就像掘金收藏頁(yè)面那個(gè)效果一樣渗鬼。
isTranslucent
的值總是 YES躬充,你也不應(yīng)該去改變它判莉,這意味著,controller 的 view 總是位于導(dǎo)航欄底下
支持通過(guò) [UINavigationBar appearance] 設(shè)置其余導(dǎo)航欄相關(guān)屬性