根据 Dima 的回答,我认为一些让人们开始的基本实施可能会有所帮助。正如 Dima 所说,它不是在移动状态栏,而是在移动状态栏的图像。
免责声明:我 YOLO 完成了这个实现,所以我不保证它是否能开箱即用
从 iOS7 开始,您可以使用
UIView *screen = [[UIScreen mainScreen] snapshotViewAfterScreenUpdates:NO];
所以基本上状态栏是从图片中裁剪出来的,并添加到上面的UIWindow
a中,这样你就可以在真实的状态栏上看到它。就像是: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
我实际上可能有兴趣尝试让它工作,所以如果是这样,我会更新。