Snapchat更新状态栏iOS7更新

Snapchat更新状态栏iOS7更新,ios,objective-c,api,private,snapchat,Ios,Objective C,Api,Private,Snapchat,在最新的snapchat更新中,当您“向右滑动查看消息”时,状态栏会以某种渐变方式从黑色变为白色 他们是如何做到这一点而不使用私有API的,还是他们使用私有API的 我调查的内容: 乍一看,我认为他们只是在做其他人都做的事情,(就像rdio目前所做的那样),通过截屏,然后修改/设置截屏动画 但是。。。您无法通过该屏幕捕获方法访问UIImage或设置其动画,因此尽管您可以移动/裁剪该屏幕快照,但无法更改其外观 所以。。。我测试了它,当状态栏处于该状态(半黑/半白)时,它仍然处于活动状态,因为它不

在最新的snapchat更新中,当您“向右滑动查看消息”时,状态栏会以某种渐变方式从黑色变为白色

他们是如何做到这一点而不使用私有API的,还是他们使用私有API的

我调查的内容:

乍一看,我认为他们只是在做其他人都做的事情,(就像rdio目前所做的那样),通过截屏,然后修改/设置截屏动画

但是。。。您无法通过该屏幕捕获方法访问UIImage或设置其动画,因此尽管您可以移动/裁剪该屏幕快照,但无法更改其外观


所以。。。我测试了它,当状态栏处于该状态(半黑/半白)时,它仍然处于活动状态,因为它不是一个屏幕截图,它会响应充电变化/信号变化等,据我所知,如果不使用私有API,这是不可能的。

这让我很好奇,所以我玩了一下应用程序,并在越狱设备上使用Spark Inspector检查了应用程序的视图层次结构,我发现了一些东西

你没有使用屏幕截图是不正确的。您要离开的一侧的状态栏是快照,不会更改。当一分钟过去时,您可以很容易地看到这一点,您正在转换到的视图的新状态栏将发生更改,因为它是真实的,而旧状态栏不会发生更改,因为它是快照。这使得幻觉很容易产生

以下是高层正在发生的事情:

  • 当您开始转换时,应用程序会在当前状态下拍摄状态栏的快照(很可能它实际上是拍摄整个
    UIScreen
    的快照,并简单地从中裁剪出状态栏),并将包含该快照的窗口附加到转换视图的顶部,锚定到最终过渡位置,并被“from”视图控制器的视图遮罩。此窗口在
    UIWindowLevelStatusBar
    上方似乎有一个
    windowLevel
    ,因此它能够覆盖真实的状态栏

  • 然后,“to”视图控制器接管实际状态栏并将其更改为“light content”状态。这呈现了一种巧妙的错觉,即单个状态栏随过渡边框而改变颜色,但真正的状态栏实际上始终位于快照窗口的下方,如果不是位于快照窗口上方的快照窗口,则在过渡开始时确实会立即可见


  • 根据Dima的回答,我认为一些基本的实现可以帮助人们开始工作。正如Dima所说,它不是移动状态栏,而是移动状态栏的图像

    免责声明:我支持此实现,因此我不保证它是否能够开箱即用

    从iOS7开始,您可以使用

    UIView *screen = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
    
    因此,基本上状态栏是从图片中裁剪出来的,并添加到
    UIWindow
    中,在
    UIWindowStatusLevelBar
    上方添加一个
    windowLevel
    ,这样您就可以在真实的状态栏上看到它。比如:

    UIWindow *statusBarWindow = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    statusBarWindow.windowLevel = UIWindowLevelStatusBar + 1; // higher
    statusBarWindow.hidden = NO; // fun fact you don't have to add a UIWindow to anything, just setting hidden = NO should display it
    statusBarWindow.backgroundColor = [UIColor clearColor]; // since visible, make it clear until we actually add the screen shot to it so as to not block anything 
    
    ...
    
    // The view that will hold the screen shot
    // Later, I think we're going to need to play with contentInsets to make the view look like its staying still, so we're making it a UIScrollView in case
    UIScrollView *statusBarView = [[UIScrollView alloc] initWithFrame:[UIApplication sharedApplication].statusBarFrame];
    statusBarView.clipsToBounds = YES;
    
    // Now we add the screen shot we took to this status bar view
    [scrollingStatusBarView addSubview:statusBarView];
    [statusBarView addSubview:screen]; // screen is the UIScrollView from previous code block (the screen shot)
    
    // Now add this statusBarView with the image to the window we created
    [statusBarWindow addSubview:statusBarView];
    
    现在,剩下的部分实际上取决于您的实现是什么样子的,但是从这里开始,您只需要使用平移或任何导致新视图从侧面进入的操作来处理视图的移动


    开始刷卡时,使用任何样式、背景或其他方式配置新的状态栏(下方的状态栏):

    [UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent animated:NO];
    // anything else you might feel like doing 
    
    现在我们有了一些有趣的事情。随着转换的进行,您必须使用滚动到“剪断”的金额来抵消
    statusBarView
    中的金额。
    statusBarView.frame
    必须从x=offset开始,否则它将显示在实际的状态栏上(因为它的窗口更高),但是如果不更改contentInsets,则图片将随着转换而滑动。因此,要创建错觉,您需要将原点向右推,同时将左侧插入的内容增加相同的数量,使其看起来位于相同的位置

    因此,在任何处理滑动动作的方法中:

    注意:这在很大程度上取决于个人实现,可能需要一些实验

     // if you're using an animation to handle the transition you can match up this change in x position with the animation
    
    // if you're doing via pan gesture you could try something like:
    CGFloat offset = self.viewThatIsScrolling.contentOffset.x; // may be negative depending on direction that is being swiped
    
    if (midTransition) { // you can use the offset value here to check
        // NOTE: again, will depend on which direction this animation is happening in. I'll assume a new view coming in from left (so swiping right)
        statusBarView.frame = CGRectMake(offset, 0, self.statusBarView.frame.width, 20.0f); // move the origin over to the right
        statusBarView.contentInsets = UIEdgeInsetsMake(0, offset, 0, 0); // make the picture start 'offset' pixels to the left so it'll look like it hasn't moved
    
    } 
    
    (旁注:您也可以尝试使用转换,而不是显式设置帧:
    statusBarView.transform=CGAffineTransformMakeTranslation(offset-previousOffsetAmount,0)
    。我在那里使用以前的偏移量,因为您只希望它以任何新的数量移动,这样它就可以匹配。如果您这样做,就必须以某种方式进行跟踪)

    最后,一旦“滑动”完成,不要忘记将屏幕截图从窗口中完全删除:

    // if continuing from before:
    if (midTransition) {
        ...
    } else { // the view has been slid completely
        [statusBarView removeFromSuperview];
        statusBarView = nil;
        // I'm keeping the UIWindow where it is for now so it doesn't have to be recreated and because it has a clear background anyways
    }
    
    // if this is being done via animation the above can be called the animation finishes
    

    我可能真的有兴趣尝试让它工作,因此如果有,我会更新。

    也许他们在转换期间重复设置状态栏的屏幕上限,并重复修改这些屏幕上限。或者,他们正在检测电池/时间/信号的变化,然后只有在这些变化时才进行屏幕封顶。显然,有一些深层次的魔法正在进行。你是对的,来自屏幕捕捉的视图,以及使用真实状态栏的视图,这就是愚弄我的原因。对上面的新窗户厚颜无耻。我想苹果公司只能阻止这一点,但仍然允许它!嘿,迪玛,回答得好。你可能想看看这个问题。显然,新的音乐应用程序只是通过状态栏实现了这一点,但它肯定是两端都有直播的。(不是snapchat使用的快照)。感谢您的评论。看起来它很可能是一个私有API,但我也会关注这个问题。他们在向下滑动通知中心覆盖(状态栏随视图动态向下滑动)中具有类似的功能已经至少一年了,因此他们肯定有一些尚未提供给我们的技巧。