一、前言
在我們IOS開發(fā)中热康,UIScrollView自帶有點擊頂部狀態(tài)欄自動返回頂部的效果凝果,不過這個效果是有約束條件的:
// When the user taps the status bar, the scroll view beneath the touch which is closest to the status bar will be scrolled to top, but only if its `scrollsToTop` property is YES, its delegate does not return NO from `shouldScrollViewScrollToTop`, and it is not already at the top.
// On iPhone, we execute this gesture only if there's one on-screen scroll view with `scrollsToTop` == YES. If more than one is found, none will be scrolled.
@property(nonatomic) BOOL scrollsToTop __TVOS_PROHIBITED; // default is YES.
即這個手勢只能作用在一個scrollView上,當發(fā)現(xiàn)多個時懒豹,手勢將會失效芙盘。
在實際應(yīng)用中,我們可能會有多個scrollView(包含UITableView/UICollectionView)脸秽,如汽車之家、網(wǎng)易新聞蝴乔、愛奇藝等等應(yīng)用记餐,這時候,系統(tǒng)默認的點擊狀態(tài)欄返回到頂部效果就會失效薇正,我們就得自己自定義控件來實現(xiàn)此功能了片酝。
二、主要技術(shù)點
拋開常用的技術(shù)點挖腰,主要用到的技術(shù)點有:
- 多窗口應(yīng)用
- 遞歸
- 坐標系轉(zhuǎn)換
- 觸摸事件響應(yīng)(橫豎屏切換時需要)
PS:由于最近剛回武漢忙著找工作雕沿,所以沒有花太多時間在簡書上面,我先把代碼放上來猴仑,后續(xù)再重新整理
#import "TopWindow.h"
@implementation TopWindow
static UIWindow *topWindow_;
/**
* 顯示頂部窗口
*/
+ (void)show
{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
topWindow_ = [[UIWindow alloc] init];
topWindow_.windowLevel = UIWindowLevelAlert;
topWindow_.frame = [UIApplication sharedApplication].statusBarFrame;
topWindow_.backgroundColor = [UIColor clearColor];
topWindow_.hidden = NO;
[topWindow_ addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(topWindowClick)]];
});
}
/**
* 監(jiān)聽頂部窗口點擊
*/
+ (void)topWindowClick
{
UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
[self searchAllScrollViewsInView:keyWindow];
}
/**
* 找到參數(shù)view中所有的UIScrollView
*/
+ (void)searchAllScrollViewsInView:(UIView *)view
{
// 遞歸遍歷所有的子控件
for (UIView *subview in view.subviews) {
[self searchAllScrollViewsInView:subview];
}
// 判斷子控件類型(如果不是UIScrollView审轮,直接返回)
if (![view isKindOfClass:[UIScrollView class]]) return;
// 找到了UIScrollView
UIScrollView *scrollView = (UIScrollView *)view;
// 判斷UIScrollView是否和window重疊(如果UIScrollView跟window沒有重疊,直接返回)
if (![scrollView bs_intersectsWithAnotherView:nil]) return;
// 讓UIScrollView滾動到最前面
// 讓CGRectMake(0, 0, 1, 1)這個矩形框完全顯示在scrollView的frame框中
[scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}
@end