簡單實現并集成一個頭部縮放的功能,適用于UIScrollView
以及其子類。
頭部伴隨模糊效果放大縮小,并在一定位置時懸停充當導航欄。這里提供實現思路,如有符合可直接使用。
效果如下圖。
ScrollView_SpringHeader.gif
<b>實現:</b>
首先分解為兩部分,一部分為頭部視圖,一部分為滾動視圖。頭部視圖負責展示,滾動視圖負責控制頭部視圖如何展示,比如放大和縮小。
<b>一:頭部視圖</b>
頭部視圖拆解為負責展示圖片的
UIImageView
,負責模糊效果的UIVisualEffectView
,負責標題顯示的UILabel
,以及返回等功能按鈕的UIButton
。進一步分析,模糊效果的視圖應該和展示圖片的視圖做同樣的處理,同樣的縮放,為了更好的控制將其包裝到一
containView
中。跟據滾動的位置改變containView
的大小,模糊視圖根據滾動的位置改變模糊的程度。標題視圖在滾動視圖到達一定位置時出現并停在那里。這里利用UIImageView
的特性,改變它的contentMode
為UIViewContentModeScaleAspectFill
,這樣只用簡單的改變圖片視圖的高度時就能營造放大縮小的效果了。
UIImageView部分代碼
_blurImageView = [[UIImageView alloc] init];
_blurImageView.clipsToBounds = YES;
_blurImageView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
_blurImageView.contentMode = UIViewContentModeScaleAspectFill;
[self addSubview:_blurImageView];
UIVisualEffectView部分代碼
UIBlurEffect *beffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleLight];
_imageEffectView = [[UIVisualEffectView alloc]initWithEffect:beffect];
_imageEffectView.alpha = 0;
_imageEffectView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth;
[self addSubview:_imageEffectView];
<b>二:滾動視圖</b>
滾動視圖需要做的就是設置 contentInset
,讓出一部分空間給頭部視圖。這里如果將頭部視圖直接加到滾動視圖上,無法做到頭部視圖最后懸停在一定位置,因此直接加到和滾動視圖同級就行。
示例代碼
self.webView = [[WKWebView alloc] initWithFrame:CGRectMake(0, 0, kWindowWidth, kWindowHeight)];
self.webView.backgroundColor = [UIColor clearColor];
[self.view addSubview:self.webView];
NSURL * url = [NSURL URLWithString:@"https://yongliangp.github.io/"];
NSMutableURLRequest *re = [NSMutableURLRequest requestWithURL:url];
[self.webView loadRequest:re];
//初始化header
self.headerView.headerImage = [UIImage imageNamed:@"saber.jpeg"];
self.headerView.tittle = @"哈哈是個demo";
self.headerView.isShowLeftButton = YES;
self.headerView.isShowRightButton = YES;
__weak typeof(self) weakSelf = self;
self.headerView.leftClickBlock = ^(UIButton *btn){
[weakSelf.navigationController popViewControllerAnimated:YES];
};
self.headerView.rightClickBlock = ^(UIButton *btn){
NSLog(@"點擊了分享");
};
[self.webView.scrollView handleSpringHeadView:self.headerView];
<b>三:控制頭部動畫</b>
和其他的滾動視圖做動畫一樣,實現滾動視圖的代理方法scrollViewDidScroll
,獲取偏移量,然后根據一定的規則做動畫,這里為了解耦,也為了復用,使用了在scrollView
的分類中監聽scrollView
的contentOffset
方法去實現動畫控制。
首先確定兩個臨界點:<b>視圖的初始高度 懸停的高度。</b>
示例代碼(簡單控制)
- (void)yl_scrollViewDidScroll:(UIScrollView *)scrollView
{
CGFloat offsetY = scrollView.contentOffset.y;
if (offsetY>=-kNavHeight)
{
offsetY=-kNavHeight;
if (self.headerView.frame.size.height!=kNavHeight)
{
self.headerView.frame = CGRectMake(0, 0, self.headerView.bounds.size.width, kNavHeight);
[UIView animateWithDuration:0.25 animations:^{
self.titleLabel.frame = CGRectMake(35, 20, self.bounds.size.width-35*2, 44);
self.titleLabel.alpha = 1;
}];
}
}else
{
self.headerView.frame = CGRectMake(0, 0, self.headerView.bounds.size.width, -offsetY);
if (self.titleLabel.alpha!=0)
{
[UIView animateWithDuration:0.25 animations:^{
self.titleLabel.frame = CGRectMake(35, 40, self.bounds.size.width-35*2, 44);
self.titleLabel.alpha = 0;
}];
}
}
CGFloat alpha ;
if (self.headerView.frame.size.height>=kWindowWidth/2)
{
alpha = 0;
}else
{
alpha = 1-((self.headerView.frame.size.height-kNavHeight)/(kWindowWidth/2-kNavHeight));
}
if (alpha>=0&&alpha<=1)
{
self.headerEffectView.alpha = alpha;
}
}
<b>最重要的,記得在控制器dealloc時移除監聽者</b>
<b>最重要的,記得在控制器dealloc時移除監聽者</b>
<b>最重要的,記得在控制器dealloc時移除監聽者</b>
或者你有更好的方式移除監聽者請告訴我。
照例放Demo,僅供參考,如有問題請留言
Demo地址:
https://github.com/yongliangP/YLSpringHeader 用心良苦請 star
如果你覺得對你有幫助請點 喜歡 哦,也可以關注 我,不定時更新(雖然現在不能保證更新量了,但會一直更??)。
或者關注 我的專題 每周至少5篇更新,多謝支持哈。