ios-自定义点击状态栏滚回顶部
点击状态栏滚回顶部这个功能是系统自带的,只需要设置self.scrollView.scrollsToTop = YES
即可,
但是这个属性有一个前提是窗口下必须只有一个可滚动的View
才有效果,这时候就需要自定义创建一个窗口
来完成这个功能。
添加窗口
- 在
AppDelegate
创建一个新的窗口必须给这个窗口设置一个根控制器,否则会报错,这里可以通过dispatch_after
来给添加窗口一个延时就可以不设置根控制器 - 窗口是有级别的
windowLevel
,级别越高就越显示在顶部,如果级别一样,那么后添加的创建显示在顶部.级别分为三种,UIWindowLevelAlert > UIWindowLevelStatusBar > UIWindowLevelNormal
,接下来创建一个创建并且添加一个监控
1 /** 2 * 显示顶部窗口 3 */ 4 + (void)show 5 { 6 dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.25 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ 7 topWindow_ = [[UIWindow alloc] init]; 8 topWindow_.windowLevel = UIWindowLevelAlert; 9 topWindow_.frame = [UIApplication sharedApplication].statusBarFrame; 10 topWindow_.backgroundColor = [UIColor clearColor]; 11 topWindow_.hidden = NO; 12 [topWindow_ addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(topWindowClick)]]; 13 }); 14 } 15 16 /** 17 * 监听顶部窗口点击 18 */ 19 + (void)topWindowClick 20 { 21 UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; 22 [self searchAllScrollViewsInView:keyWindow]; 23 } 24 25 /** 26 * 找到参数view中所有的UIScrollView 27 */ 28 + (void)searchAllScrollViewsInView:(UIView *)view 29 { 30 // 递归遍历所有的子控件 31 for (UIView *subview in view.subviews) { 32 [self searchAllScrollViewsInView:subview]; 33 } 34 35 36 // 判断子控件类型(如果不是UIScrollView,直接返回) 37 if (![view isKindOfClass:[UIScrollView class]]) return; 38 39 // 找到了UIScrollView 40 UIScrollView *scrollView = (UIScrollView *)view; 41 42 // 判断UIScrollView是否和window重叠(如果UIScrollView跟window没有重叠,直接返回) 43 if (![scrollView bs_intersectsWithAnotherView:nil]) return; 44 45 // 让UIScrollView滚动到最前面 46 // 让CGRectMake(0, 0, 1, 1)这个矩形框完全显示在scrollView的frame框中 47 [scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES]; 48 }
注意有个uiscrollview的分类,里面加上这个方法。
- (BOOL)bs_intersectsWithAnotherView:(UIView *)anotherView { if (anotherView == nil) anotherView = [UIApplication sharedApplication].keyWindow; // 判断self和anotherView是否重叠 CGRect selfRect = [self convertRect:self.bounds toView:nil]; CGRect anotherRect = [anotherView convertRect:anotherView.bounds toView:nil]; return CGRectIntersectsRect(selfRect, anotherRect); }
以上方法可以判断不是同一坐标系的2个View
是否重叠,并且如果anotherView
为空的话,就返回窗口
在监听方法中加入以上代码即可完成功能