Snapchat更新状态栏iOS7更新
Posted
技术标签:
【中文标题】Snapchat更新状态栏iOS7更新【英文标题】:Snapchat update status bar iOS7 update 【发布时间】:2014-06-28 13:50:48 【问题描述】:在最新的 snapchat 更新中,当您“向右滑动查看消息”时,状态栏会以一种渐变的方式从黑色变为白色。
http://imgur.com/osJI20u
他们如何在不使用私有 API 的情况下做到这一点,或者他们是否使用私有 API?
我调查的内容:
乍一看,我以为他们只是在做其他人所做的事情(就像 rdio 目前所做的那样),通过屏幕捕获整个屏幕,然后修改/动画化该屏幕截图。
但是...您无法通过该屏幕捕获方法访问 UIImage 或为其设置动画,因此尽管您可以移动/裁剪该屏幕截图,但您无法更改其外观。
所以...我对其进行了测试,当状态栏处于该状态(半黑/半白)时,它仍然是 LIVE,因为它不是屏幕截图,并且它响应充电变化/信号变化等,据我所知,如果不使用私有 API,这是不可能的。
【问题讨论】:
也许他们在转换过程中反复对状态栏进行屏幕截图并反复修改这些屏幕截图。或者他们可能会检测电池/时间/信号的变化,然后仅在这些情况发生变化时才进行屏幕覆盖。 显然有一些深奥的魔法正在酝酿中。 【参考方案1】:这让我很好奇,所以我稍微玩了一下这个应用程序,并在越狱设备上使用 Spark Inspector 检查了应用程序的视图层次结构,我发现了一些东西。
您对他们不使用屏幕截图的看法是错误的。您正在离开的那一侧的状态栏是一个快照,不会改变。一分钟后您可以轻松地看到这一点,您正在转换到的视图的新状态栏将发生变化,因为它是真实的,但旧状态栏不会因为它是快照。这使得这种错觉很容易解决。
以下是高层次上正在发生的事情:
当您开始转换时,应用程序会在其当前状态下拍摄状态栏的快照(很可能它实际上是在拍摄整个 UIScreen
的快照并简单地从其中裁剪状态栏)并将包含该快照的窗口附加到转换中视图的顶部,锚定到最终转换位置并由“来自”视图控制器的视图屏蔽。此窗口似乎在UIWindowLevelStatusBar
上方有一个windowLevel
,因此它能够覆盖真实的状态栏。
然后,“to”视图控制器接管实际状态栏并将其更改为“light content”状态。这呈现出一种巧妙的错觉,即单个状态栏会随着过渡边框改变颜色,但真正的状态栏实际上总是位于快照窗口下方,并且如果不是快照窗口就在过渡开始时确实会立即可见在它之上。
【讨论】:
你说得对,来自的视图是截屏,而来自的视图是使用真实的状态栏,这就是愚弄我的原因。上面的新窗口厚颜无耻。我猜苹果只能阻止这种做法,但仍然允许这样做! 嘿迪玛,很好的答案。您可能想看看这个问题***.com/questions/31378595/…。显然,新的音乐应用程序通过状态栏做到了这一点,但它肯定在两端都存在。 (不是像 snapchat 使用的快照)。 感谢您的评论。看起来它很可能是一个私有 API,但我也会关注这个问题。他们在向下滑动通知中心覆盖(状态栏随着视图动态向下滑动)中具有类似的功能至少一年了,所以他们肯定有一些尚未提供给我们的技巧。 【参考方案2】:根据 Dima 的回答,我认为一些基本的实施可以帮助人们入门。正如 Dima 所说,它不是在移动状态栏,而是在移动状态栏的图像。
免责声明:我 YOLO 完成了这个实现,所以我不保证它是否能开箱即用
从ios7开始你可以使用拍照
UIView *screen = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
所以基本上状态栏是从图片中裁剪出来的,并添加到UIWindow
和windowLevel
上方的UIWindowStatusLevelBar
,这样你就可以在真实的状态栏上看到它。比如:
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);
。我在那里使用 previousOffsetAmount 是因为您只希望它移动任何新数量,以便它可以匹配. 如果你走这条路,就必须以某种方式跟踪)
最后,一旦“滑动”完成,不要忘记将屏幕截图从窗口中完全删除:
// 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更新状态栏iOS7更新的主要内容,如果未能解决你的问题,请参考以下文章
iOS 7 状态栏和 self.view.frame 和 self.view.bounds
在 Safari 和 Chrome 中更改 iOS 7 状态栏的颜色