iOS隐藏和取消隐藏状态栏没有正确移动子视图
我有一个可以包含两个子视图控制器的自定义视图控制器。当设备处于纵向方向时,其中一个控制器的视图变得可见。当设备处于横向方向时,其他控制器的视图变为可见。然而,当横向取向视图可见时,状态栏会缩回以为特定视图留出更多空间。设备重新转换为纵向模式后,状态栏不显示。这是自定义视图控制器显示在UINavigationController
内。iOS隐藏和取消隐藏状态栏没有正确移动子视图
我的问题是,当状态栏的可见性变化时,我的子视图不能正确调整。有最终被一个大的间隙和/或重叠,当开启设备在不同的取向,如下图所示:
正如你可以看到,它最初是细(纵向),但是当该装置被关,状态栏是白色的空白处。当设备转回肖像时,UINavigationController
的导航栏会显示并与状态栏重叠,导航栏与其下方视图之间会出现间隙。如果从一个风景方向到另一个风景方向旋转180度非常快,则间隙消失并且看起来很好。
下面的方法属于自定义视图控制器和willAnimateRotationToInterfaceOrientation:duration:
被称为(显然处理旋转事件)和viewDidAppear:
(处理当视图从以前视图控制器在被推入导航栈)。
- (void)cueAnimationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation fromViewDidAppear:(BOOL) fromViewDidAppear
{
// Fading animation during orientation flip.
// Make sure its not already animating before trying.
BOOL barHidden = [UIApplication sharedApplication].statusBarHidden;
if (!isAnimating) {
BOOL alreadyGoodGrid = (UIInterfaceOrientationIsLandscape(interfaceOrientation) && curView == self.gridViewController.view);
BOOL alreadyGoodTable = (UIInterfaceOrientationIsPortrait(interfaceOrientation) && curView == self.tableViewController.view);
if ((alreadyGoodGrid && barHidden) ||
(alreadyGoodTable && !barHidden)) {
// If views are the way they should be for this orientation. Don't do
// anything.
return;
}
isAnimating = YES;
UIView *nextView;
// Get starting orientation. This will determine what view goes on top
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
nextView = self.gridViewController.view;
else
nextView = self.tableViewController.view;
if (nextView == self.tableViewController.view)
{
if (!alreadyGoodTable)
{
self.tableViewController.view.alpha = 0.0;
[self.view bringSubviewToFront:self.tableViewController.view];
}
// Unhide the bar for the table view
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
}
else // gridViewController
{
if (!alreadyGoodGrid)
{
self.gridViewController.view.alpha = 0.0;
[self.view bringSubviewToFront:self.gridViewController.view];
}
// Hide the bar for the grid view
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}
[UIView animateWithDuration:0.4
delay: 0.0
options: UIViewAnimationOptionAllowUserInteraction
animations:^{
if (nextView == self.tableViewController.view) {
self.tableViewController.view.alpha = 1.0;
}
else {
self.gridViewController.view.alpha = 1.0;
}
}
completion:^(BOOL finished) {
if (nextView == self.tableViewController.view) {
curView = self.tableViewController.view;
}
else {
curView = self.gridViewController.view;
}
isAnimating = NO;
}];
}
}
非常感谢任何人,可以花时间看看这个。
很多人似乎都有这个问题,因为我有,而且还有其他有关它的Q/A线索,你应该寻找 - 我可能永远找不到神奇的答案。在某些情况下,您可能会试图解决问题的一种方法是在将条形可见性更改为(重新)显示状态条时:
- 隐藏导航栏。
- 取消隐藏状态栏。
- 取消隐藏导航栏。
或隐藏,隐藏,取消隐藏如果你隐藏状态栏。
有时候人们发现在隐藏导航栏之前需要略微延迟 - 所以在异步调度块中在下一个runloop上运行。例如:
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController setNavigationBarHidden:NO animated:NO];
});
在摆弄了很多东西之后,我似乎想出了一些解决方案。它似乎工作没有失败。
这里是我的代码:
- (void)cueAnimationToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation fromViewDidAppear:(BOOL) fromViewDidAppear
{
// Fading animation during orientation flip.
// Make sure its not already animating before trying.
BOOL barHidden = [UIApplication sharedApplication].statusBarHidden;
if (!isAnimating) {
BOOL alreadyGoodGrid = (UIInterfaceOrientationIsLandscape(interfaceOrientation) && curView == self.gridViewController.view);
BOOL alreadyGoodTable = (UIInterfaceOrientationIsPortrait(interfaceOrientation) && curView == self.tableViewController.view);
if ((alreadyGoodGrid && barHidden) ||
(alreadyGoodTable && !barHidden)) {
// If views are the way they should be for this orientation. Don't do
// anything.
return;
}
isAnimating = YES;
UIView *nextView;
// Get starting orientation. This will determine what view goes on top
if (UIInterfaceOrientationIsLandscape(interfaceOrientation))
nextView = self.gridViewController.view;
else
nextView = self.tableViewController.view;
if (nextView == self.tableViewController.view)
{
if (!alreadyGoodTable)
{
self.tableViewController.view.alpha = 0.0;
[self.view bringSubviewToFront:self.tableViewController.view];
}
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationSlide];
}
else
{
if (!alreadyGoodGrid)
{
self.gridViewController.view.alpha = 0.0;
[self.view bringSubviewToFront:self.gridViewController.view];
}
[[UIApplication sharedApplication] setStatusBarHidden:YES withAnimation:UIStatusBarAnimationSlide];
}
[UIView animateWithDuration:0.4
delay: 0.0
options: UIViewAnimationOptionAllowUserInteraction
animations:^{
CGRect r = self.navigationController.navigationBar.frame;
if (nextView == self.tableViewController.view) {
self.tableViewController.view.alpha = 1.0;
self.navigationController.navigationBar.frame = CGRectMake(0.0, 20.0, r.size.width, r.size.height);
self.view.frame = CGRectMake(0.0, 20.0, self.view.frame.size.width, self.view.frame.size.height - 20.0);
}
else {
self.gridViewController.view.alpha = 1.0;
self.navigationController.navigationBar.frame = CGRectMake(0.0, 0.0, r.size.width, r.size.height);
double y = 0.0, h = 0.0;
if (fromViewDidAppear)
{
y = -20.0;
h = 20.0;
}
self.view.frame = CGRectMake(0.0, y, self.view.frame.size.width, self.view.frame.size.height + h);
}
}
completion:^(BOOL finished) {
if (nextView == self.tableViewController.view) {
curView = self.tableViewController.view;
}
else {
curView = self.gridViewController.view;
}
isAnimating = NO;
}];
}
}
我要做的就是检查是否该方法正在从viewDidAppear:
叫或其他地方(在这种情况下,只有willAnimateRotationToInterfaceOrientation:duration:
)。取决于谁调用方法,情况会有所不同。在任何一种情况下,我都会调整self.view.frame
和self.navigationController.navigationBar.frame
以解决状态栏位置的差异。当我们来自viewDidAppear:
我需要抛出状态栏高度的负y值,以使子视图正常向上移动。这似乎都似乎工作得很好。
我在隐藏状态栏和导航栏重叠后出现同样的问题,然后再次显示。我在github here(见showUI
方法)上找到了一个解决方案,我修改了它以适合我的需要。
- (void)toggleNavBar:(BOOL)hide
{
navBarHidden = hide;
//Fade status bar
[[UIApplication sharedApplication] setStatusBarHidden:hide
withAnimation:UIStatusBarAnimationFade];
//Fade navigation bar
[UINavigationBar beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.3]; // Approximately the same time the status bar takes to fade.
self.navigationController.navigationBar.alpha = hide ? 0 : 1;
[UINavigationBar commitAnimations];
// Being invisible messes with the position of the navigation bar, every time it gets
// visible we need to set it to the correct y-offset (just below the status bar)
[self adjustNavBarOrigin];
}
-(void)adjustNavBarOrigin
{
CGRect r = self.navigationController.navigationBar.frame;
r.origin.y = 20; //Height of the statusbar, can't find a reliable method in the SDK to get this value
self.navigationController.navigationBar.frame = r;
}
为ios7,覆盖prefersStatusBarHidden
- (BOOL)prefersStatusBarHidden {
return NO if landscape and NO if landscape;
}
的方向变化调用函数低于触发prefersStatusBarHidden功能
[self setNeedsStatusBarAppearanceUpdate];
这解决了详细的解答我的问题:
self.automaticallyAdjustsScrollViewInsets = false
你能否在你的回答中解释为什么它解决了你的问题? – Zulu 2014-11-29 01:27:38
我的问题是,当我试图在包含子视图的视图中隐藏导航/状态栏时,子视图将随顶部栏移动。最近我发现问题与插入设置。 – 2014-11-29 01:47:41
感谢您的帮助。对你有好处。我确实得到了另一个解决方案,似乎很好,我只是作为答案发布。 – 2013-03-04 03:40:57
很高兴你找到了一些东西 - 也许它会帮助我! – 2013-03-04 16:12:46