美文网首页ios键盘上的鼓手iOS开发指南
iOS-点击状态栏返回到顶部效果

iOS-点击状态栏返回到顶部效果

作者: Super_Yi | 来源:发表于2015-12-31 22:41 被阅读10066次
一、前言

在我们IOS开发中,UIScrollView自带有点击顶部状态栏自动返回顶部的效果,不过这个效果是有约束条件的:


// 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上,当发现多个时,手势将会失效。
在实际应用中,我们可能会有多个scrollView(包含UITableView/UICollectionView),如汽车之家、网易新闻、爱奇艺等等应用,这时候,系统默认的点击状态栏返回到顶部效果就会失效,我们就得自己自定义控件来实现此功能了。

二、主要技术点

抛开常用的技术点,主要用到的技术点有:

  • 多窗口应用
  • 递归
  • 坐标系转换
  • 触摸事件响应(横竖屏切换时需要)
PS:由于最近刚回武汉忙着找工作,所以没有花太多时间在简书上面,我先把代码放上来,后续再重新整理

#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)]];
    });
}

/**
 * 监听顶部窗口点击
 */
+ (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;
    
    // 判断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

相关文章

网友评论

  • xiao小马哥:其实不用这么麻烦,你只要设置其中想要回到顶部的scrollview的scrollToTop属性为YES,其他的都为NO,就可以了
  • CoderJackieYip:这种方法,可行是可行,MJ的方案,不过有个巨坑啊。比如分享功能:从当前app跳转到分享微博app,然后跳转回来自己的app之后,状态栏上左上角会显示“返回微博”。此时点击“返回微博”,就没办法响应 了,因为点击事件被这个topWindow接收了。
  • 90823cc8f71b:当action sheet弹出时,UIWindowDidResignKeyNotification通知被发送了。此时检查app所在的window,发现它已经不再是key window了。那么通过[UIApplication sharedApplication].keyWindow,获取window进行操作时,就会出错,请问怎么解决?
  • JaromeHuang:状态栏被改为黑色的了
  • 885389eb08b2:上面的人都确定能用???iOS9之后不是都得给window加一个根控制器???要不直接崩溃!!
    Dayu大鱼:@沙子LOVE 我吧window 的背景色 clearColor 了 , 我的能运行, 你试试
    沙子LOVE:@Hissia Xcode 7 现在也都得给window加一个根控制器 ,不管什么iOS系统。。 我加了根控制器,能实现功能,但顶部发生变化了,一坨黑,你有出现吗? 你是怎么解决的???
  • 茄子_Apple:现在是在武汉工作吗?
    coderboy001:@i_茄子 成都
  • d9431116937e:不知道出现这个问题没有,点击二级页面的状态栏,如果不进行上拉刷新操作,能正常回滚到原来的位置,但是如果上拉刷新了,回滚上去下拉刷新控件会出现在原来-offset.y的位置
  • d994dc68be77:大神 按照你的方法做了 确实有用了,但是进入二级页面 状态栏的字体是变成黑色的 调用任何方法都改不过来 怎么办呢
    Super_Yi:@如意葫芦 没明白你的表述
    d9431116937e:@如意葫芦 两种解决方案:1.在info.plist中增加一个字段,就是那个View controller-based status bar appearance,二级页面设置白色,返回时再设置过来
    2.二级页面设置窗口隐藏,返回时显示
  • 系统盘:很显然,我的失效了,我也用的这个方法,但是到一个scrollerview承载多个tableview时候,不知道发什么疯没用
  • YimG: [scrollView setContentOffset:CGPointMake(scrollView.contentOffset.x, 0) animated:YES];
    :stuck_out_tongue_winking_eye:
  • YimG:如果一个ScrollView 里面有多个并排的tablview 那怎么办?
    Super_Yi:@YimG 递归遍历所有的ScrollView,找到和窗口重叠的,会返回的顶部,其他的不会返回
  • iHTCboy:判断UIScrollView是否和window重叠(如果UIScrollView跟window没有重叠,直接返回)
    这个方法的代码是什么?
    6e7261f07368:@iHTCboy 然后最后一句换成这个 [scrollView setContentOffset:CGPointMake(0, 0) animated:YES];
    最后居然行了, :joy:
    6e7261f07368:@iHTCboy 我硬是写成这个了,不知道对不对 if (!( (topWindow_.frame.origin.x+topWindow_.frame.size.width >=scrollView.frame.origin.x) && (topWindow_.frame.origin.x+topWindow_.frame.size.width <= scrollView.frame.origin.x+scrollView.frame.size.width)))
    return;

本文标题:iOS-点击状态栏返回到顶部效果

本文链接:https://www.haomeiwen.com/subject/flxwhttx.html