带有 UISegmentedControl 的 UINavigationBar 部分覆盖了 childViews

UINavigationBar with UISegmentedControl partially covers childViews

我已经阅读了许多关于此主题和 Apple 文档的其他主题,但尚未找到针对我的特定问题的解决方案。

我的应用程序使用 UITabBarController 作为 rootViewController,在其中一个选项卡中,我在 navigationBar 中有一个 UISegmentedControl 以在三个子 [=] 之间切换16=]s.

(在实际应用中,有两个 childVC 是自定义的 UIViewController,我只是在示例应用中使用了三个 UITableViewController)。

segmentedControl 设置和切换都工作正常。出错的是只有第一个 UITableViewController 被正确显示。对于第二个和第三个,第一个单元格的一部分隐藏在 navigationBar 下。当我三个都点进去的时候,第一个还是可以的

我制作了一个小示例应用程序来展示正在发生的事情,使用非常明亮的颜色进行演示:https://www.dropbox.com/s/7pfutvn5jba6rva/SegmentedControlVC.zip?dl=0

这里还有一些代码(我没有使用故事板):

// AppDelegate.m

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    FirstViewController *fvc = [[FirstViewController alloc] init];
    UINavigationController *firstNavigationController = [[UINavigationController alloc] initWithRootViewController: fvc];

    SecondViewController *svc = [[SecondViewController alloc] init];
    UINavigationController *secondNavigationController = [[UINavigationController alloc] initWithRootViewController: svc];

    // Initialize tab bar controller, add tabs controllers
    UITabBarController *tabBarController = [[UITabBarController alloc] init];
    tabBarController.viewControllers = @[firstNavigationController, secondNavigationController];

    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    self.window.rootViewController = tabBarController;
    [self.window makeKeyAndVisible];

    return YES;
}


// FirstViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.

    self.title = @"One";
    self.view.backgroundColor = [UIColor orangeColor];

    UITableViewController *vc1 = [[UITableViewController alloc] init];
    UITableViewController *vc2 = [[UITableViewController alloc] init];
    UITableViewController *vc3 = [[UITableViewController alloc] init];

    vc1.view.backgroundColor = [UIColor redColor];
    vc2.view.backgroundColor = [UIColor blueColor];
    vc3.view.backgroundColor = [UIColor greenColor];

    self.viewControllers = @[vc1, vc2, vc3];
    self.segmentTitles = @[@"Red", @"Blue", @"Green"];

    self.segmentedControl = [[UISegmentedControl alloc] initWithItems: self.segmentTitles];
    [self.segmentedControl addTarget: self
                              action: @selector(segmentClicked:)
                    forControlEvents: UIControlEventValueChanged];

    self.navigationItem.titleView = self.segmentedControl;

    self.segmentedControl.selectedSegmentIndex = 0;

 // set the first child vc:  
    UIViewController *vc = self.viewControllers[0];

    [self addChildViewController: vc];
    vc.view.frame = self.view.bounds;
    [self.view addSubview: vc.view];
    self.currentVC = vc;
}

- (void)segmentClicked:(id)sender
{
    if (sender == self.segmentedControl)
    {
        NSUInteger index = self.segmentedControl.selectedSegmentIndex;
        [self loadViewController: self.viewControllers[index]];
    }
}

- (void)loadViewController:(UIViewController *)vc
{
    [self addChildViewController: vc];

    [self transitionFromViewController: self.currentVC
                      toViewController: vc
                              duration: 1.0
                               options: UIViewAnimationOptionTransitionFlipFromBottom
                            animations: ^{
                                [self.currentVC.view removeFromSuperview];
                                vc.view.frame = self.view.bounds;
                                [self.view addSubview: vc.view];
                            } completion: ^(BOOL finished) {
                                [vc didMoveToParentViewController: self];
                                [self.currentVC removeFromParentViewController];
                                self.currentVC = vc;
                            }
     ];
}

很明显,我的问题是,为什么会发生这种情况,我该如何解决?

编辑:添加屏幕截图。

编辑:根据下面的答案,我将动画块中的代码更改为:

[self.currentVC.view removeFromSuperview];

if ([vc.view isKindOfClass: [UIScrollView class]])
{
    UIEdgeInsets edgeInsets = UIEdgeInsetsMake(self.topLayoutGuide.length, 0, self.bottomLayoutGuide.length, 0);
    [UIView performWithoutAnimation: ^{
      vc.view.frame = self.view.bounds;
       ((UIScrollView *)vc.view).contentInset = edgeInsets;
         ((UIScrollView *)vc.view).scrollIndicatorInsets = edgeInsets;
     }];
  }
   else
   {
       vc.view.frame = self.view.bounds;
   }

   [self.view addSubview: vc.view];

现在可以了。我也打算用自定义 UIViewController 试试这个。

问题是您没有为每个 table 视图设置正确的内容插图。系统会尝试为您做这件事,但我猜您的设置对它来说太复杂了,而且它只为 viewDidLoad 中加载的第一个 table 视图做这件事。在您的 loadViewController: 方法中,当替换当前显示的视图时,确保将 contentInsetscrollIndicatorInsets 都设置为前一个视图的值。我认为系统稍后会设法设置正确的插图,以防您旋转到横向。尝试一下。如果没有,您将需要在 viewDidLayoutSubviews.

中自行完成