码皇之路之 iOSiOS开发好文

JJStatusBarExtension 完美实现点击 stat

2016-02-24  本文已影响270人  德蒙_托尔斯泰

背景

动手

// JJStatusBarExtension.m
static JJStatusBarExtension *_topWindow;

+ (instancetype)sharedStatusBarExtension
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _topWindow = [[self alloc] init];
    });
    return _topWindow;
}

+ (instancetype)allocWithZone:(struct _NSZone *)zone
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        _topWindow = [super allocWithZone:zone];
    });
    return _topWindow;
}

- (id)copyWithZone:(NSZone *)zone
{
    return _topWindow;
}

+ (void)showWithStatusBarClickBlock:(void (^)())block
{
    if (_topWindow) return;
    
    [JJStatusBarExtension sharedStatusBarExtension].windowLevel = UIWindowLevelAlert;
    [JJStatusBarExtension sharedStatusBarExtension].backgroundColor = [UIColor clearColor];
    // 先显示window
    [JJStatusBarExtension sharedStatusBarExtension].hidden = NO;
    
    // 设置根控制器
    JJTopViewController *topVc = [[JJTopViewController alloc] init];
    topVc.view.backgroundColor = [UIColor clearColor];
    topVc.view.frame = [UIApplication sharedApplication].statusBarFrame;
    topVc.view.autoresizingMask = UIViewAutoresizingFlexibleWidth;
    topVc.clickedBlock = block;
    [JJStatusBarExtension sharedStatusBarExtension].rootViewController = topVc;
}

- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
{
    if (point.y > 20) {
        return nil;
    }
    return [super hitTest:point withEvent:event];
}
// AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

//    NSLog(@"%@", self.window);
    [JJStatusBarExtension showWithStatusBarClickBlock:^{
//        [self test];
        // 如果想要 app的所有界面都有点击 statusBar 滚到最前面, 则调用下面这个方法
        [JJStatusBarExtension scrollToTopInsideView:self.window];
    }];
    
    return YES;
}
+ (void)scrollToTopInsideView:(UIView *)view
{
    CGRect viewRect = [view convertRect:view.bounds toView:nil];
    if (!CGRectIntersectsRect([UIApplication sharedApplication].keyWindow.frame, viewRect)) {
        return;
    }
    
    for (UIView *subview in view.subviews) {
        [self scrollToTopInsideView:subview];
    }
    if (![view isKindOfClass:[UIScrollView class]]) {
        return;
    }
    UIScrollView *scrollView = (UIScrollView *)view;
    //    CGPoint contentOffset = scrollView.contentOffset;
    //    contentOffset.y = - scrollView.contentInset.top;
    //    [scrollView setContentOffset:contentOffset animated:YES];
    [scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}

完成上面的控件部署, 下面就实现功能实现部分

- (BOOL)prefersStatusBarHidden
{
    return YES;
}
- (UIStatusBarStyle)preferredStatusBarStyle
{
    return UIStatusBarStyleDefault;
}

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
    return UIStatusBarAnimationFade;
}
// UIViewController (JJStatusBarExtension) --分类
@implementation UIViewController (JJStatusBarExtension)

+ (void)load
{
  // 交换系统 viewWillAppear 和我们自定义的 jj_viewWillAppear
    Method method1 = class_getInstanceMethod(self, @selector(jj_viewWillAppear:));
    Method method2 = class_getInstanceMethod(self, @selector(viewWillAppear:));
    method_exchangeImplementations(method1, method2);
}

- (void)jj_viewWillAppear:(BOOL)animated
{
    [self jj_viewWillAppear:animated];
    // 如果非当前窗口显示的控制器, 我只测试到UINavigationController下,"UIInputWindowController"会产生影响, 把它屏蔽掉
//    NSLog(@"%@", self.class);
    if ([NSStringFromClass(self.class) isEqualToString:@"UIInputWindowController"]) return;

    if ([self respondsToSelector:@selector(jj_ignoreStatusBar)]) {
    if ([self jj_ignoreStatusBar]) return;
    }

    JJTopViewController *statusBarVc = (JJTopViewController *)[JJStatusBarExtension sharedStatusBarExtension].rootViewController;
    if (statusBarVc == self) return;
    statusBarVc.showingVc = self;
    // 判断是否设置动画
    if (statusBarVc.showingVc.preferredStatusBarUpdateAnimation == UIStatusBarAnimationNone) {
        [statusBarVc setNeedsStatusBarAppearanceUpdate];
    }else{
        [UIView animateWithDuration:[JJStatusBarExtension sharedStatusBarExtension].statusBarAnimationDuration animations:^{
            [statusBarVc setNeedsStatusBarAppearanceUpdate];
        }];
    }
}
@end
@interface JJTopViewController : UIViewController
@property(nonatomic, strong) void(^clickedBlock)();
@property(nonatomic, strong) UIViewController * showingVc;
@end

@implementation JJTopViewController

- (BOOL)prefersStatusBarHidden
{
    return self.showingVc.prefersStatusBarHidden;
}

- (UIStatusBarStyle)preferredStatusBarStyle
{
    return self.showingVc.preferredStatusBarStyle;
}

- (UIStatusBarAnimation)preferredStatusBarUpdateAnimation
{
    return self.showingVc.preferredStatusBarUpdateAnimation;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    if (self.clickedBlock) {
        self.clickedBlock();
    }
}

@end

以上就是所有实现的主要思路以及代码

以上就是所有内容了, 有什么不对的地方望请指出, 大家互相学习...有什么问题请留言

上一篇下一篇

猜你喜欢

热点阅读