解决点击状态栏时ScrollView自动滚动到初始位置失效办法

scrollView自带一个功能,当用户点击顶部的状态栏时,scrollView的ContentOffset.y轴会自动滚动到初始位置,单个scrollView单击顶部状态栏系统自带功能展示这个功能对用户来说非常实用,可是功能在当前控制器有多个scrollView(TableView, WebView, CollectionView一切继承scrollView的控件)的时候就会失效.

下面给出解决办法:

首先创建一个topWindow继承至NSObject,这里我们考虑将这个功能完全封装起来,所以所有的方法都用的类方法,所以用最基本的类就可以
在initialize方法中初始化topWIndow,将topWIndow的级别改成最高的UIWindowLevelAlert级别,设置topWindow位置,并且添加点击手势
在topWIndow被点击调用的方法中,我们拿出UIApplication的keyWindow,遍历keyWindow的所有子控件,如果满足是scrollView同时又显示在当前keyWindow条件时,将subView的contentOffset的y值回复到原始
然后采用递归的套路在遍历subView内时候有满足条件的子控件,直到没有满足条件时会停止

objective-c代码

.h文件只暴露显示和隐藏方法
#import <Foundation/Foundation.h>
@interface TopWindow : NSObject
+(void)show;
//+ (void)hide;
@end
.m文件只暴露显示和隐藏方法
@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)]];
    });
}

/**
 * 监听顶部窗口点击
 */
+ (void)topWindowClick
{
    UIWindow *keyWindow = [UIApplication sharedApplication].keyWindow;
    [self searchAllScrollViewsInView:keyWindow];
}

/**
 * 找到参数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;
    
    CGRect scrollViewRect = [scrollView convertRect:scrollView.bounds toView:nil];
    CGRect keyWindowRect = [UIApplication sharedApplication].keyWindow.bounds;

    // 判断UIScrollView是否和window重叠(如果UIScrollView跟window没有重叠,直接返回)
    if (!CGRectIntersectsRect(scrollViewRect, keyWindowRect)) return;
    
    // 让UIScrollView滚动到最前面
    // 让CGRectMake(0, 0, 1, 1)这个矩形框完全显示在scrollView的frame框中
    [scrollView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}

@end
在AppDelegate.m中调用
#import "AppDelegate.h"
#import "TopWindow.h"
@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    [TopWindow show];
    
    return YES;
}

现在整个项目中,当用户点击顶部的状态栏时,scrollView的ContentOffset.y轴会自动滚动到初始位置了!

原文地址:https://www.cnblogs.com/jyking/p/6737211.html