【问题标题】:UIView doesn't resize to full screen when hiding the nav bar & tab bar隐藏导航栏和标签栏时,UIView 不会调整为全屏
【发布时间】:2010-11-09 18:01:13
【问题描述】:

我有一个带有标签栏和导航栏的应用程序,用于正常交互。我的一个屏幕是大部分文本,所以我允许用户点击进入全屏(有点像 Photos.app)。

导航栏和标签栏被隐藏,我将文本视图的框架设置为全屏。问题是,标签栏曾经所在的位置大约有 50 像素的空白区域。你可以从这个屏幕截图中看到:

删除了无效的 ImageShack 链接

我不确定是什么原因造成的。空白绝对不是文本视图后面的视图,因为我将它的背景颜色设置为红色只是为了确定。这可能是什么原因造成的?

** 更新 **

我在 UIWindow 子类中进行了一些命中测试,发现空白实际上是未记录/未发布的 UILayoutContainerView。这是 tabBar 的父视图。我觉得不建议直接操作这个视图,那怎么隐藏标签栏呢?

** 更新 #2 **

我在动画前后检查了 self.view 的帧,看起来父视图的大小调整不够。

全屏后,视图的框架只有 411 像素高。我试过手动弄乱框架,也没有运气设置 autoResizeMask。

**** 更新:这是最终结果****

- (void)toggleFullscreen {
    isFullScreen = !isFullScreen;  //ivar
    
    //hide status bar & navigation bar
    [[UIApplication sharedApplication] setStatusBarHidden:isFullScreen animated:YES];
    [self.navigationController setNavigationBarHidden:isFullScreen animated:YES];
    
    [UIView beginAnimations:@"fullscreen" context:nil];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:.3];
    
    //move tab bar up/down
    CGRect tabBarFrame = self.tabBarController.tabBar.frame;
    int tabBarHeight = tabBarFrame.size.height;
    int offset = isFullScreen ? tabBarHeight : -1 * tabBarHeight;
    int tabBarY = tabBarFrame.origin.y + offset;
    tabBarFrame.origin.y = tabBarY;
    self.tabBarController.tabBar.frame = tabBarFrame;
    
    //fade it in/out
    self.tabBarController.tabBar.alpha = isFullScreen ? 0 : 1;
    
    //resize webview to be full screen / normal
    [webView removeFromSuperview];
    if(isFullScreen) {
                //previousTabBarView is an ivar to hang on to the original view...
        previousTabBarView = self.tabBarController.view;
        [self.tabBarController.view addSubview:webView];

        webView.frame = [self getOrientationRect];  //checks orientation to provide the correct rect
        
    } else {
        [self.view addSubview:webView];
        self.tabBarController.view = previousTabBarView;
    }
    
    [UIView commitAnimations];
}

(请注意,我将 textview 切换为 webview,但对于原始文本视图也是如此)

【问题讨论】:

  • 您的图片链接似乎已损坏。如果您仍有原始图像,请将其重新上传到 stack.imgur,或者只是编辑您的问题以使其在没有图像的情况下工作。谢谢。

标签: iphone iphone-sdk-3.0 uitextview


【解决方案1】:

我遇到了这个确切的问题,我分别在屏幕底部和顶部对标签栏和导航栏进行了动画处理,在标签栏所在的位置留下了 49 像素高的空白区域。

事实证明,我的新“全屏”视图实际上没有填充空间的原因是因为我将全屏视图添加为导航控制器视图的子视图,导航控制器视图本身是标签栏控制器的子视图。

为了解决这个问题,我只是将新的全屏视图(在您的情况下是包含所有文本的视图)添加为 UITabBarController 视图的子视图。

[[[self tabBarController] view] addSubview:yourTextView];

那么你需要做的就是确保你的子视图的框架是 480 x 320px 并且它应该填满屏幕(包括以前神秘的空白区域)

【讨论】:

  • 这种工作,但我发现没有简单的方法可以回到常规视图。 self.tabBarController.view = previousView 似乎有奇怪的副作用...
  • 我最终得到了这个方法。旋转确实让这个行为有点奇怪,所以我最终只是在全屏模式下手动设置 web 视图的框架。
【解决方案2】:

您绝对可以通过移动视图的框架使标签栏离开屏幕来使某些内容看起来正确。我知道其他人提到尝试过,而您说它不起作用,但我怀疑问题是您尝试时没有正确设置 textviews 调整掩码大小。下面是应该工作的代码:

- (void)viewDidLoad {
  [super viewDidLoad];
  currentlyHidden = NO;
}

- (void) hideStuff {
  SO2AppDelegate *appDelegate = (id)[[UIApplication sharedApplication] delegate];
  self.navigationController.navigationBarHidden = YES;

  CGRect newFrame = appDelegate.tabBarController.view.frame;
  newFrame.size.height += appDelegate.tabBarController.tabBar.frame.size.height;
  appDelegate.tabBarController.view.frame = newFrame;
}

- (void) showStuff {
  SO2AppDelegate *appDelegate = (id)[[UIApplication sharedApplication] delegate];

  CGRect newFrame = appDelegate.tabBarController.view.frame;
  newFrame.size.height -= appDelegate.tabBarController.tabBar.frame.size.height;
  appDelegate.tabBarController.view.frame = newFrame;

  self.navigationController.navigationBarHidden = NO;
}

- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {  
  if (currentlyHidden) {
    [self showStuff];
    currentlyHidden = NO;
  } else {
    [self hideStuff];
    currentlyHidden = YES;
  }
}

此外,由于这对您的笔尖等设置非常敏感,我是posting 一个在线项目,因此您可以下载并查看它。这是一个非常简单的演示,只是一个基于导航的项目,其中委托设置了一个选项卡控制器并从主 nib 嵌入视图控制器。其余的在 RootViewController nib 和类中。每当触摸开始时,条就会切换,因此只需点击屏幕。显然,在一个真实的应用程序中,您可能需要调整滚动视图,以便内容不会出现跳跃。

【讨论】:

  • 我尝试了您的示例并且它有效,但由于某种原因我无法将它翻译到我的应用程序中。看起来我在做同样的事情(尽管不是通过应用程序委托,我是查看 self.tabBarController)。我最终将 textview 添加到 tabBarController 的视图并手动调整大小。无论如何,我很欣赏详细的答案。我希望我能对你们俩表示信任。
【解决方案3】:

您是否将视图控制器的hidesBottomBarWhenPushed 属性设置为YES?您需要在 initWithNibName:bundle:initWithCoder: 方法中设置它。当它被推送到导航控制器时,它应该隐藏标签栏并使内容视图向下延伸到底部。

【讨论】:

  • 这行得通,但不是我想要的行为。我需要能够通过点击进入和退出全屏。这适用于导航/状态栏,但不适用于标签栏。
【解决方案4】:

也许有另一个视图是标签栏区域的内置部分?也就是说,要隐藏一些额外的东西。这将帮助您查看周围的视图。

for (UIView *viewy in [self.navigationController.view subviews])
{
    NSLog([viewy description]);
}

【讨论】:

  • 视图:> > > >(这显示了 navigationController 子视图和 tabBarController 子视图)
  • 这给了我一个想法,让我在白色区域进行命中测试,看看会出现什么视图。我用更多细节更新了问题。
【解决方案5】:

我发现,如果您标记新视图,您将推送到导航堆栈上,下面的行将隐藏标签栏,只要它在堆栈上。

scrollViewController.hidesBottomBarWhenPushed = YES;

【讨论】:

    【解决方案6】:

    我有类似的问题。正如Harry 提到的,导航控制器是标签栏控制器的内部控制器的原因。找到了另一种如何重绘视图并拥有正确框架的方法。,在您的控制器中添加以下内容:

    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
    
        // Here you can make your tabBarControlelr.view.hidde = true or use any animation that hides UITabBar. I made
        [TabBarController setTabBarHidden:YES];
    
        self.navigationController.view.frame = CGRectMake(self.navigationController.view.frame.origin.x, self.navigationController.view.frame.origin.y, self.navigationController.view.frame.size.width, self.navigationController.view.frame.size.height + 50);
        [self.navigationController.view setNeedsLayout];
    
     }
    

    这就是我隐藏它的方式。我可以让它直接调用 TabBarControlelr 的方法或类方法包装器:

    + (void)setTabBarHidden:(BOOL)hidden
    {
        AppDelegate *delegate = [UIApplication sharedApplication].delegate;
        TabBarController *tabBarController = (TabBarController *) delegate.window.rootViewController;
    
        if ([tabBarController isKindOfClass:[TabBarController class]]) {
            [tabBarController setTabBarHidden:hidden];
        }
    }
    
    
    - (void)setTabBarHidden:(BOOL)hidden
    {
        if (self.tabBar.hidden == hidden) {
            return;
        }
    
        if (hidden == NO) {
            self.tabBar.hidden = hidden;
        }
    
        [UIView animateWithDuration:0.15 animations:^{
            self.tabBar.frame = CGRectOffset(self.tabBar.frame, 0, ( hidden ? 50 : -50 ));
        } completion:^(BOOL finished) {
            self.tabBar.hidden = hidden;
        }];
    }
    

    【讨论】:

      【解决方案7】:

      我认为问题在于您仍在标签栏控制器中,我也遇到了一些问题,最终创建了两个视图供我的应用委托控制,标签栏控制器和一个单独的 uiview,它包含选项卡栏控制器试图控制的任何内容。您可以将您的视图传递给应用程序委托并在那里使用它吗?

      【讨论】:

      • 我不确定我是否遵循...你是说当我全屏使用完全不同的视图时?我尝试将视图直接添加到 UIWindow,看起来不错,但旋转时的体验相当古怪。我不确定我想走这条路。
      【解决方案8】:

      尝试使 TabBarControllers 视图大于屏幕,以便标签栏隐藏在屏幕之外,只要您在设置新的 ViewController 之前这样做,那么它的视图将调整大小以填充新框架!

      在我的测试中,我使用了 tabBarController:shouldSelectViewController: 委托方法来检查哪个视图控制器将成为当前视图并相应地设置 TabBarController.view.frame。例如:

      - (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController
      {
          if( viewController == second)
              tabBarController.view.frame = CGRectMake( 0, 20, 320, 500);
          else
              tabBarController.view.frame = CGRectMake( 0, 20, 320, 460);
      }
      

      如果这仍然不是您所需要的,请尝试查看 UIViewController 的 hidesBottomBarWhenPushed 属性。当设置为 yes 时,如果控制器被推到导航堆栈上,这将使底部栏隐藏。

      【讨论】:

        【解决方案9】:

        当您选择全屏时,我会将视图移至窗口。例如

        myView = [self.view retain];
        self.view = nil;
        [window addSubview:myView];
        

        然后返回:

        [myView removeFromSuperView];
        self.view = myView;
        [myView release];
        myView = nil;
        

        通过将视图添加为窗口的子窗口,它可以完全全屏并位于标签栏的顶部。

        然后您可以将其与

        结合使用
        [[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(didRotate:) name:@"UIDeviceOrientationDidChangeNotification" object:nil];
        

        检测旋转。 (我认为您将其与 view.transform = CGAffineTransformMakeRotation 结合以使其旋转...?)

        【讨论】:

        • 当我这样做时,有什么提示可以让轮换工作吗?如果我这样做,它似乎不会调用我的 shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation 方法。
        • 您可以结合使用当前解决方案:[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications]; [[NSNotificationCenter defaultCenter] addObserver:self 选择器:@selector(didRotate:) name:@"UIDeviceOrientationDidChangeNotification" object:nil];检测旋转。 (我认为您将其与 view.transform = CGAffineTransformMakeRotation 结合以使其旋转...?)您可以从 didRotate: 函数中调用您的 shouldAutorotateToInterface... 函数来查看您是否也应该这样做。
        【解决方案10】:

        如果您使用的是 Interface Builder,请确保在 Size Inspector 中正确设置自动调整大小。 如果您在代码中创建 UITextView,请确保将框架设置为足够大,并且视图的父级(以及它的父级)也足够大。为简单起见,直接将视图添加到窗口中,然后从那里向内移动。

        将视图移动到其父视图:

        - (void)moveViewToSuperview:(UIView *)view
        {
            UIView *newSuperview = [[view superview] superview];
            [view removeFromSuperview];
            [newSuperview addSubview:view];
            [newSuperview bringSubviewToFront:view];
        }
        

        【讨论】:

        • 自动尺寸为 W+H。 textView.frame = CGRectMake(0,0, 320, 700);似乎对它没有影响。
        • 如果我从视图中删除文本视图,然后将其直接添加到窗口中,则它会全屏显示。不过,这有奇怪的自动旋转效果,所以我不能这样。它似乎确实表明某些东西遮挡了文本视图。
        • 试试这个:将你的 UITextView 返回到它在 Interface Builder 中的原始位置。在视图变得可见后添加对 moveViewToSuperview:myTextView 的调用运行您的应用程序。测试它是否被遮挡。如果没有,请添加另一个调用并再次调试。冲洗重复。这应该可以帮助您弄清楚阻碍文本视图的视图“有多少级”。
        【解决方案11】:

        您是否尝试过强制文本“重写”自身(重置您正在使用的任何对象的 .text 属性)?我遇到过很多情况,其中视图根本不重新检查或重新绘制其数据,而强制似乎是唯一的解决方法。如果从用户体验的角度来看这不是很好,您可以尝试在用户触摸后和消失之前使导航/标签栏透明。这通常会将视图扩展到屏幕的全尺寸。

        【讨论】:

        • 如果我使状态栏透明并将 setWantsFullScreenLayout 属性设置为“是”,那么它会在顶部而不是底部标签栏。
        【解决方案12】:

        如果 UITabBarController 是由 rootViewController (navigationController) 推送的。您可以尝试以下方法:

        先隐藏状态栏/标签栏;

        [self.navigationController pushViewController:aBlankViewController animated:NO];
        [self.navigationController popViewControllerAnimated:NO];
        

        你应该可以回收空白,虽然屏幕在调整过程中会震动...

        【讨论】:

          【解决方案13】:

          我遇到过类似的问题,这个讨论很有帮助:UIWebView on iPad size

          Tony 的回答帮助我发现,当您创建子视图时,设置类似这样的代码会很有帮助:

          self.tabBarController.tabBar.frame = self.view.bounds;
          

          【讨论】:

            【解决方案14】:

            像这样将代码放在为 segue 做准备中,非常适合我:

            - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
            {
            if ([[segue identifier] isEqualToString:@"ViewPhoto"]) {
            
                ImageView *vc = [segue destinationViewController];
            
                NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
            
                    NSString *Title = [photoNames objectAtIndex:selectedIndex];
                    [vc setSelectedTitle:[NSString stringWithFormat:@"%@", Title]];
            
                    vc.hidesBottomBarWhenPushed = YES;
            
                    }
                }
            

            【讨论】:

              【解决方案15】:

              将额外的空间添加到视图的尺寸中,所以如果它是矩形 CGRectMake(0,0,320,460) 使其成为 CGRectMake(0,0,320,480)...这发生在我身上,我不知道为什么,这可能与您将文本视图置于顶部的底层视图有关,但只需添加维度即可

              【讨论】:

              • 这没有任何效果。
              猜你喜欢
              • 1970-01-01
              • 2011-04-15
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2013-08-14
              • 1970-01-01
              • 1970-01-01
              相关资源
              最近更新 更多