寫了什么衷掷?
一個十分普及且好看的tableHeaderView+NavigationBar的組合效果印蔬。雖然有很多大牛都寫過類似的開源項(xiàng)目回论。出于學(xué)習(xí)swift的目的,寫了一個swift版本挑随,具體效果見下圖状您。最終版代碼已經(jīng)上傳到GitHub[ParallaxHeaderView][id]
[id]: https://github.com/SmallLang/ParallaxHeaderView "ParallaxHeaderView"
準(zhǔn)備工作
開發(fā)xcode7、swift2.0镀裤。新建一個swift項(xiàng)目并達(dá)到如下截圖所示效果竞阐。
編碼
1:NavigationBar顏色漸變效果
細(xì)心的人一看就知道要達(dá)到所說的即顏色漸變效果無疑是兩個步驟
1:設(shè)置NavigationBar的顏色
2:設(shè)置在tableView滾動的過程中NavigationBar的透明度缴饭,其實(shí)還是設(shè)置顏色
那么目的是十分明了的---我要改變NavigationBar的顏色暑劝。那么問題又來了,如何改變NavigationBar的顏色颗搂?方法很多担猛,只列出下面三種
直接修改 NavigationBar的barTintColor屬性。
(失敗的嘗試丢氢,不想了解可以跳過)
self.navigationController?.navigationBar.barTintColor = UIColor(red: 0/255.0, green: 130/255.0, blue: 210/255.0, alpha: 1)
看起來還不錯的樣子(StatusBar的顏色稍后再做調(diào)整)傅联,緊接著嘗試在活動過程中修改它的透明度。
override func scrollViewDidScroll(scrollView: UIScrollView) {
//NavBar及titleLabel透明度漸變
let color = UIColor(red: 0/255.0, green: 130/255.0, blue: 210/255.0, alpha: 1)
let offsetY = scrollView.contentOffset.y
let prelude: CGFloat = 50
if offsetY >= -64 {
let alpha = min(1, (64 + offsetY) / (64 + prelude))
//NavBar透明度漸變
self.navigationController?.navigationBar.barTintColor = color.colorWithAlphaComponent(1 - alpha)
} else {
self.navigationController?.navigationBar.barTintColor = color.colorWithAlphaComponent(1)
}
}
這里便出現(xiàn)問題了疚察,不管我怎么更改它顏色的透明度都是沒有用的(更改顏色有效)蒸走。這時候靈機(jī)一動,直接修改navigationBar的透明度貌嫡!
override func scrollViewDidScroll(scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
let prelude: CGFloat = 50
if offsetY >= -64 {
let alpha = min(1, (64 + offsetY) / (64 + prelude))
//NavBar透明度漸變
self.navigationController?.navigationBar.alpha = 1 - alpha
} else {
self.navigationController?.navigationBar.alpha = 1
}
}
咦比驻?好像是對的哦!仔細(xì)看岛抄,導(dǎo)航欄的首頁兩個字也變透明了别惦,回頭看示例效果圖,星期一標(biāo)題可沒有變紅夫椭。進(jìn)行到這里掸掸,我也找不到解決方式了(如果你有方法請留言指教)。
利用navigationBar的backgroundColor與其他屬性的組合
(失敗的嘗試,不想了解可以跳過)
self.navigationController?.navigationBar.backgroundColor = UIColor(red: 0/255.0, green: 130/255.0, blue: 210/255.0, alpha: 1)
看起來有點(diǎn)奇怪扰付,雖然看到藍(lán)色了堤撵,但是好像上面有點(diǎn)東西,為了滿足好奇用了一下Reveal查看了下圖層結(jié)構(gòu)悯周,發(fā)現(xiàn)上面的確有一層圖層名字里面含有EffectView,于是上網(wǎng)一查粒督,果然有解決方式.
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default) //用一個空的image替換掉哪層模糊的效果
self.navigationController?.navigationBar.shadowImage = UIImage()//同樣是使用一個空的image替換掉分割線,不懂的話可以注釋這行禽翼,然后把下面顏色alpha設(shè)置成0看看就知道了
self.navigationController?.navigationBar.backgroundColor = UIColor(red: 0/255.0, green: 130/255.0, blue: 210/255.0, alpha: 1)
}
狀態(tài)欄顏色沒變屠橄。。闰挡。這是個大問題锐墙,因?yàn)樵O(shè)置狀態(tài)欄顏色很復(fù)雜所以這種方式又放棄了(同樣請求指教)
利用objc_getAssociatedObject關(guān)聯(lián)
想法來自于第二的實(shí)驗(yàn)的失敗,因?yàn)榭吹絥avigationBar還有上面那么多圖層长酗,于是我想能不能自定義一個view添加到navigationBar上呢溪北?然后在通過控制這個view的顏色從而達(dá)到顏色漸變效果呢?
當(dāng)然你可以嘗試創(chuàng)建一個navigationBar的子類夺脾,然后用kvc替換掉系統(tǒng)自帶的(為啥用kvc之拨?因?yàn)閚avigationBar是只讀),當(dāng)然也可以直接addsubView咧叭,這兩種方式對后續(xù)的操作都會造成很大困擾所以我就沒有進(jìn)行嘗試蚀乔,當(dāng)然你也可以去試一試。我要來介紹的是我使用的方法菲茬。
擴(kuò)展UINavigationBar吉挣,并用objc_getAssociatedObject為UINavigationBar添加一個屬性。
objc_getAssociatedObject與objc_getAssociatedObject是runtime的一些知識婉弹,但這里只用到皮毛還是比較好理解的
var key: String = "coverView"
extension UINavigationBar {
/// 定義的一個計算屬性睬魂,如果可以我更希望直接頂一個存儲屬性。它用來返回和設(shè)置我們需要加到
/// UINavigationBar上的View
var coverView: UIView? {
get {
//這句的意思大概可以理解為利用key在self中取出對應(yīng)的對象,如果沒有key對應(yīng)的對象就返回niu
return objc_getAssociatedObject(self, &key) as? UIView
}
set {
//與上面對應(yīng)是重新設(shè)置這個對象镀赌,最后一個參數(shù)如果學(xué)過oc的話很好理解氯哮,就是代表這個newValue的屬性
//OBJC_ASSOCIATION_RETAIN_NONATOMIC意味著:strong,nonatomic
objc_setAssociatedObject(self, &key, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
func setMyBackgroundColor(color: UIColor) {
if self.coverView != nil {
self.coverView!.backgroundColor = color
}else {
self.setBackgroundImage(UIImage(), forBarMetrics: .Default)
self.shadowImage = UIImage()
let view = UIView(frame: CGRectMake(0, -20, UIScreen.mainScreen().bounds.size.width, CGRectGetHeight(self.bounds) + 20))
view.userInteractionEnabled = false
view.autoresizingMask = [.FlexibleHeight, .FlexibleWidth]
self.insertSubview(view, atIndex: 0)
view.backgroundColor = color
self.coverView = view
}
}
}
上面就是擴(kuò)展方法,接下來是進(jìn)行測試代碼
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.setMyBackgroundColor(UIColor(red: 0/255.0, green: 130/255.0, blue: 210/255.0, alpha: 1))
}
override func scrollViewDidScroll(scrollView: UIScrollView) {
//NavBar及titleLabel透明度漸變
let color = UIColor(red: 0/255.0, green: 130/255.0, blue: 210/255.0, alpha: 1)
let offsetY = scrollView.contentOffset.y
let prelude: CGFloat = 50
if offsetY >= -64 {
let alpha = min(1, (64 + offsetY) / (64 + prelude))
//NavBar透明度漸變
self.navigationController?.navigationBar.setMyBackgroundColor(color.colorWithAlphaComponent(1-alpha))
} else {
self.navigationController?.navigationBar.setMyBackgroundColor(color.colorWithAlphaComponent(1))
}
}
這樣就差不多了商佛,而且使用的擴(kuò)展喉钢,用起來十分的方便。而且也沒有阻擋到導(dǎo)航控制器事件的傳遞威彰。
2:tableHeaderView部分
宿舍要關(guān)門了出牧。。見后續(xù)文章_
<link rel="stylesheet" >
<script src="http://7xnwdv.com1.z0.glb.clouddn.com/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>