标签:
点击状态栏ScrollView(包括子控件)自动滚到顶部
这里就直接将解决思路一一写出来不将代码分段展示了,在代码中我加了详细的注释objective-c的套路和swift基本一样,在最后会将Swift和objective-c的代码一起放上,如果需要直接解决问题的童鞋可以直接将代码拷贝到工程里即可
首先创建一个topWindow继承至NSObject,这里我们考虑将这个功能完全封装起来,所以所有的方法都用的类方法,所以用最基本的类就可以
在initialize方法中初始化topWIndow,将topWIndow的级别改成最高的UIWindowLevelAlert级别,设置topWindow位置,并且添加点击手势
在topWIndow被点击调用的方法中,我们拿出UIApplication的keyWindow,遍历keyWindow的所有子控件,如果满足是scrollView同时又显示在当前keyWindow条件时,将subView的contentOffset的y值回复到原始
然后采用递归的套路在遍历subView内时候有满足条件的子控件,直到没有满足条件时会停止
Swift的代码
1 import UIKit 2 class TopWindow: UIWindow { 3 private static let window_: UIWindow = UIWindow() 4 /// 类初始化方法,保证window_只被创建一次 5 override class func initialize() { 6 window_.frame = CGRectMake(0, 0, global.appWidth, 20) 7 window_.windowLevel = UIWindowLevelAlert 8 window_.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "topWindowClick")) 9 } 10 class func topWindowClick() { 11 // 遍历当前主窗口所有view,将满足条件的scrollView滚动回原位 12 searchAllowScrollViewInView(UIApplication.sharedApplication().keyWindow!) 13 } 14 private class func searchAllowScrollViewInView(superView: UIView) { 15 for subview: UIView in superView.subviews as! [UIView] { 16 if subview.isKindOfClass(UIScrollView.self) && superView.viewIsInKeyWindow() { 17 // 拿到scrollView的contentOffset 18 var offest = (subview as! UIScrollView).contentOffset 19 // 将offest的y轴还原成最开始的值 20 offest.y = -(subview as! UIScrollView).contentInset.top 21 // 重新设置scrollView的内容 22 (subview as! UIScrollView).setContentOffset(offest, animated: true) 23 } 24 // 递归,让子控件再次调用这个方法判断时候还有满足条件的view 25 searchAllowScrollViewInView(subview) 26 } 27 } 28 /// 添加topWindow,使手势生效 29 class func showTopWindow() { 30 window_.hidden = false 31 } 32 /// 隐藏topWindow,移除手势 33 class func hiddenTopWindow() { 34 window_.hidden = true 35 } 36 } 37 /// 对UIView的一个扩展 38 extension UIView { 39 /// 判断调用方法的view是否在keyWindow中 40 func viewIsInKeyWindow() -> Bool { 41 let keyWindow = UIApplication.sharedApplication().keyWindow! 42 // 将当前view的坐标系转换到window.bounds 43 let viewNewFrame = keyWindow.convertRect(self.frame, fromView: self.superview) 44 let keyWindowBounds = keyWindow.bounds 45 // 判断当前view是否在keyWindow的范围内 46 let isIntersects = CGRectIntersectsRect(viewNewFrame, keyWindowBounds) 47 // 判断是否满足所有条件 48 return !self.hidden && self.alpha > 0.01 && self.window == keyWindow && isIntersects 49 } 50 }
在AppDelegate里,程序启动完成方法时添加就OK了
1 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { 2 // 添加顶部的window 3 TopWindow.showTopWindow() 4 return true 5 }
需要注意添加了自定义的window后,控制器的改变状态栏状态方法会失效,可以在info.plist中将改变状态栏的管理权交给UIApplication解决,或者在需要改变状态栏的控制器中调用TopWindow.hiddenTopWindow()即可,或者直接改info.plist,用UIApplication.sharedApplication().setStatusBarStyle来管理
objective-c代码
.h文件只暴露显示和隐藏方法
1 @interface WNXTopWindow : NSObject 2 + (void)show; 3 + (void)hide; 4 @end
.m文件
1 #import "WNXTopWindow.h" 2 @implementation WNXTopWindow 3 static UIWindow *window_; 4 //初始化window 5 + (void)initialize { 6 window_ = [[UIWindow alloc] init]; 7 window_.frame = CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, 20); 8 window_.windowLevel = UIWindowLevelAlert; 9 [window_ addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(windowClick)]]; 10 } 11 + (void)show { 12 window_.hidden = NO; 13 } 14 + (void)hide { 15 window_.hidden = YES; 16 } 17 // 监听窗口点击 18 + (void)windowClick { 19 UIWindow *window = [UIApplication sharedApplication].keyWindow; 20 [self searchScrollViewInView:window]; 21 } 22 + (void)searchScrollViewInView:(UIView *)superview { 23 for (UIScrollView *subview in superview.subviews) { 24 // 如果是scrollview, 滚动最顶部 25 if ([subview isKindOfClass:[UIScrollView class]] && [subview isShowingOnKeyWindow]) { 26 CGPoint offset = subview.contentOffset; 27 offset.y = - subview.contentInset.top; 28 [subview setContentOffset:offset animated:YES]; 29 } 30 // 递归继续查找子控件 31 [self searchScrollViewInView:subview]; 32 } 33 } 34 + (BOOL)isShowingOnKeyWindow:(UIView *)view { 35 // 主窗口 36 UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow; 37 // 以主窗口左上角为坐标原点, 计算self的矩形框 38 CGRect newFrame = [keyWindow convertRect:view.frame fromView:view.superview]; 39 CGRect winBounds = keyWindow.bounds; 40 // 主窗口的bounds 和 self的矩形框 是否有重叠 41 BOOL intersects = CGRectIntersectsRect(newFrame, winBounds); 42 return !view.isHidden && view.alpha > 0.01 && view.window == keyWindow && intersects; 43 } 44 @end 45 同样,也是在程序初始化完成AppDelegate文件中显示topWindow,整个工程这个问题就统统解决了 46 47 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 48 // 添加一个window, 点击这个window, 可以让屏幕上的scrollView滚到最顶部 49 [WNXTopWindow show]; 50 return YES; 51 }
iOS开发——实战技术OC篇&点击状态栏ScrollView(包括子控件)自动滚到顶部
标签:
原文地址:http://www.cnblogs.com/iCocos/p/4733430.html