答案似乎是容器视图的自动调整大小掩码根本不与状态栏协调。除了编写代码调整布局别无选择。
由于 Apple 没有提供 statusBar 和其他元素之间的自动协调,你会认为他们会让我们自己做。但是,不,我们不允许直接设置 statusBar 框架。动画 statusBar 重新定位的唯一方法是 via UIStatusBarAnimationSlide
,它使用自己的时间线,永远不会匹配其他动画。
但是,我们可以控制 statusBar 淡入淡出的时间,并随之滑动容器视图。子视图的自动调整大小掩码将完成其余的工作。这实际上看起来相当不错,并且编码虽然因一些奇怪的框架行为而变得复杂,但并不太痛苦:
UIApplication *appShared = [UIApplication sharedApplication];
CGFloat fStatusBarHeight = appShared.statusBarFrame.size.height; // best to get this once and store it as a property
BOOL bHideStatusBarNow = !appShared.statusBarHidden;
CGFloat fStatusBarHeight = appDelegate.fStatusBarHeight;
if (bHideStatusBarNow)
fStatusBarHeight *= -1;
CGRect rectView = self.view.frame; // must work with frame; changing the bounds won't have any effect
// Determine the container view's new frame.
// (The subviews will autoresize.)
switch (self.interfaceOrientation) {
case UIInterfaceOrientationPortrait:
case UIInterfaceOrientationPortraitUpsideDown:
rectView.origin.y += fStatusBarHeight;
rectView.size.height -= fStatusBarHeight;
break;
case UIInterfaceOrientationLandscapeLeft:
case UIInterfaceOrientationLandscapeRight:
// In landscape, the view's frame will sometimes complement the orientation and sometimes not.
/*
Specifically, if view is loaded in landscape, its frame will reflect that; otherwise, the frame will always be in portrait orientation.
This is an issue only when the navBar is present. Regular view controllers can count on the frame staying in portrait orientation no matter what.
But regular view controllers have another oddity: In the upside-down orientations, you should adjust the height only; the origin takes care of itself.
*/
if (rectView.size.width < rectView.size.height) {
rectView.origin.x += fStatusBarHeight;
rectView.size.width -= fStatusBarHeight;
}
else {
rectView.origin.y += fStatusBarHeight;
rectView.size.height -= fStatusBarHeight;
}
break;
default:
break;
}
// The navBar must also be explicitly moved.
CGRect rectNavBar = [self.navigationController.navigationBar frame];
rectNavBar.origin = CGPointMake(0.0f, rectNavBar.origin.y + fStatusBarHeight);
// Perform the animated toggling and reframing.
[UIView animateWithDuration:kAnimDurationToggleStatusBar animations:^{
[appShared setStatusBarHidden:bHideStatusBarNow]; // you can add withAnimation:UIStatusBarAnimationSlide here and it will work, but the timing won't match
[self.navigationController.navigationBar setFrame:rectNavBar];
[self.view setFrame:rectView];
}];
无需对工具栏进行任何操作,它仍然粘在屏幕底部——只要您没有将窗口框架设置为 mainScreen.bounds。
一个障碍是当您想要重新显示它时如何获取 statusBar 高度,因为statusBarFrame
如果它当前隐藏,则返回一个 0 区域的矩形。事实证明,做一个初步的显示/隐藏,没有动画,只是为了得到矩形,工作正常。没有可见的闪光。
此外,如果您使用的是 xib/nib,请确保其视图的 statusBar 设置为 None。
也许有一天苹果会增强 statusBar 布局行为。然后所有这些代码,对于每个视图控制器,都必须重做......