前言:
時間軸如下:
1 .首先看一遍實(shí)現(xiàn)效果還有源碼,源碼這里下載:https://github.com/Ade0408/PersonDetailPage
2 .花一個早上的時間實(shí)現(xiàn)還有各個細(xì)節(jié)點(diǎn)分析
3 .差不多一個下午的時間寫總結(jié)
4.本文僅僅供個人學(xué)習(xí)記錄
效果如下:
demo.gif
- 拖動效果:
- 向上滑動時,HeadView會跟著向上滑動,并且滑動到選項(xiàng)卡的區(qū)域時,就不會再向上滑動
- 向下滑動時,HeadView的高度會隨著拉動而變大,實(shí)現(xiàn)放大背景圖的效果
思路如下:
- 1 . 搭建界面布局,設(shè)置好約束(注意 : HeadView 和 選項(xiàng)卡都是直接添加到主View上的,并不是在TableView上)
- 2 . HeadView 背景圖注意點(diǎn):需要設(shè)置背景圖片的內(nèi)容模式為
UIViewContentModeScaleAspectFill(內(nèi)容填充)
,只有設(shè)置成這個才能隨著HeadView的變大而變大,但是還有需要注意的是,同時我們還需要設(shè)置把圖片多出來的部分給剪切掉,因?yàn)?UIViewContentModeScaleAspectFill(內(nèi)容填充)
是同比例變大,所以會有多出的部分,可以通過設(shè)置imageV的clipsToBounds
屬性為YES
- 3 . 設(shè)置一些常量屬性:
- HeadView 高度
- HeadView 最小高度 (當(dāng)?shù)扔谶@個最小高度時,狀態(tài)欄才會完全顯示出來)
- 選項(xiàng)卡高度
- 原始偏移量 : - (HeadView 高度 + 選項(xiàng)卡高度),注意:該常量是負(fù)的,該原始偏移量就是tableView的 contentOffset.y
- 4 . 接下來可以開始寫代碼了,我們目前需要做4件事:
- 4.1 把導(dǎo)航欄完全隱藏
- 4.2 把導(dǎo)航欄上的文字隱藏
- 4.3 把tableView的內(nèi)容下移244個單位(HeadView 高度+選項(xiàng)卡高度)
- 4.4 讓底下的tableView不要自動滾動64個單位
- (void) setNavgationBarHide {
/** 把tableview視圖整體往下移動244個單位,因?yàn)檫@一部分是頭部視圖還有選項(xiàng)卡的大小 */
// kHeaderViewHeight 和 kChooseViewHeight 都是前面說到的常量,一個是200,一個是44
self.contentTableView.contentInset = UIEdgeInsetsMake(kHeaderViewHeight+kChooseViewHeight,0, 0, 0);
/** 不要自動往下滾動64個單位.(64是原本狀態(tài)欄還有導(dǎo)航欄的高度合) */
self.automaticallyAdjustsScrollViewInsets = NO;
/** 設(shè)置導(dǎo)航欄為透明,其原理就是傳入一個沒有圖片,但又不為空的UIImage給導(dǎo)航欄 */
[self.navigationController.navigationBar setBackgroundImage:[[UIImage alloc]init] forBarMetrics:UIBarMetricsDefault];
/** 把導(dǎo)航欄上的分隔線用一個沒有圖片,但又不為空的UIImage給覆蓋掉 */
[self.navigationController.navigationBar setShadowImage:[[UIImage alloc] init]];
/** 添加自定義title */
UILabel *contentLable = [[UILabel alloc] init];
contentLable.text = @"微博個人詳情頁面";
/** 讓label根據(jù)文字的大小自己調(diào)整大小 */
[contentLable sizeToFit];
self.navigationItem.titleView = contentLable;
/** 默認(rèn)隱藏title */
contentLable.textColor = [UIColor colorWithWhite:0 alpha:0];
/** 讓控制器的self.contentLabel指向contentLable,這樣方便我們后續(xù)對它進(jìn)行操作 */
self.contentLabel = contentLable;
}
- 5 . 這時你可以先給tableView設(shè)置一些假數(shù)據(jù),使它等會可以拖動到底部
- 6 . 使用 UIScrollView 的代理方法 (
scrollViewDidScroll:
) 監(jiān)聽滾動事件 - 7 . 這是最重要的一步,總體效果都在這里進(jìn)行實(shí)現(xiàn),雖然都是在 UIScrollView 代理方法里進(jìn)行實(shí)現(xiàn),但是還是分開來寫.這里我們需要把它拆分成幾個步驟來做:
- 7.1 計(jì)算偏移量,這個偏移量的計(jì)算公式為:用戶滾動視圖的偏移量 - 原始偏移量,也就是如下公式:
微博詳情頁面offset計(jì)算思路.png
/** 計(jì)算偏移量,originalOffset也就是上面提到的原始偏移量,因?yàn)槲覀儼裻ableView往下移動了244個單位,所以這個原始偏移量就是這個值 */
CGFloat offset = scrollView.contentOffset.y - originalOffset;
- 7.2 計(jì)算偏移高度
// 偏移高度 = 默認(rèn)高度 - 偏移量
CGFloat offsetHeight = kHeaderViewHeight - offset;
- 7.3 設(shè)置headView 的高度隨著下拉或上拉而變化 (注意點(diǎn) : HeadView的最小高度是64,我們在前面已經(jīng)設(shè)置過這個常量了,那么當(dāng)偏移高度小于這個值時,我們默認(rèn)設(shè)置為這個值,并且通過設(shè)置這個值,我們還可以實(shí)現(xiàn)選項(xiàng)卡懸停效果) :
/** 懸停效果,其實(shí)就是不讓圖片的高度繼續(xù)減小,最小只能是64 */
if (offsetHeight < kHeaderViewMinHeight) {
offsetHeight = kHeaderViewMinHeight;
}
/** 通過修改Height達(dá)到效果,當(dāng)向上滾動時,選項(xiàng)卡向上滾動的速度比頭部視圖的還要快一點(diǎn) */
self.headViewHeightConstraint.constant = offsetHeight;
效果如圖:
微博詳情頁面實(shí)現(xiàn)懸停效果.png
- 7.4 程序?qū)懙竭@里,其實(shí)大部分效果都實(shí)現(xiàn)了,但是還差一個導(dǎo)航欄和導(dǎo)航欄上的文字隨著向上拉動而逐漸顯示,實(shí)現(xiàn)代碼如下:
// alpha 值計(jì)算 : 偏移量 / (headView默認(rèn)高度 - headView最小高度) ,當(dāng)大于1時,導(dǎo)航欄和contentLabel就會完全顯示
CGFloat alpha = offset / (kHeaderViewHeight - kHeaderViewMinHeight);
// 前面我們設(shè)置好的 contentLabel ,可以在這里去動態(tài)設(shè)置它的alpha值
self.contentLabel.textColor = [UIColor colorWithWhite:0 alpha:alpha];
// 這里直接使用袁崢的Category方法,返回一張通過傳入顏色,返回一張1*1的圖片,navigationBar會圖片拉伸填充到整個導(dǎo)航欄
[self.navigationController.navigationBar setBackgroundImage:[UIImage imageWithColor:[UIColor colorWithWhite:1 alpha:alpha]] forBarMetrics:UIBarMetricsDefault];
結(jié)語:
若大家在觀看本文的過程發(fā)現(xiàn)我有任何的理解錯誤,可以在本文下進(jìn)行評論,我會第一時間進(jìn)行修改,最后,謝謝您的閱讀!
我的源碼地址:https://github.com/Ade0408/PersonDetailPage