14

UITabBarController在 iOS7 上遇到了一个奇怪的问题,似乎找不到解决方法,所以欢迎任何帮助!

设想:

  • 在 iPad 上使用横向方向的基于导航的应用程序。
  • 应用程序由一个主视图和一个 UITabBarController 的第二个视图组成。
  • TabBarController 有两个选项卡。
  • 第一个视图有两个按钮 - 每个按钮对标签栏控制器执行一个 segue 并将不同的标签设置为选中。(即 button1 选择第一个选项卡,而 button2 选择第二个选项卡)。
  • prepareForSegue通过调用setSelectedIndex标签栏控制器来设置标签。

演示问题的简单故事板

结果:

在 iOS 7 上,我发现选项卡栏控制器中显示的视图无法在视图的右侧边缘注册任何触摸事件!所以在上图的storyboard中,不能点击屏幕右侧的UISwitch。

我什至在视图上附加了一个轻击手势识别器,并用它来记录可以触摸的屏幕区域——它似乎记录了大约 x=770 点的触摸事件。屏幕的剩余 1/4 是“不可触摸的”!

在 segue 之后,如果您手动切换到另一个选项卡并再次切换回来,则触摸事件是“固定的”,并且完整视图会再次响应触摸。

这在 iOS 5 / 6 上似乎不是问题。

任何帮助非常感谢:

  1. 首先是什么导致这种情况发生(iOS7错误/更改?)
  2. 我还能如何解决这个问题?我试过打电话setSelectedViewController和使用setSelectedIndex,这似乎是一样的。

提前致谢。

4

5 回答 5

13

我最终向开发人员技术支持提出了这个问题,它看起来像一个错误。这是我从 Apple 收到的回复:

标签栏控制器设置为包含您的视图控制器的容器视图未调整大小以考虑界面处于横向。显示视图控制器时的尺寸为 768(宽度)x 1024(高度)。

显示所选选项卡的视图时,视图层次结构如下所示:

UIWindow
    /* Navigation Controller */
    UILayoutContainerView
        UINavigationTransitionView
            UIViewControllerWrapperView
                /* Tab bar controller */
                UILayoutContainerView
                    UITransitionView
                        UIViewControllerWrapperView <-- Incorrectly sized.
                            /* MyViewController */
                            MyViewController.view

UIViewControllerWrapperView 的大小不正确不会导致显示问题,因为即使子视图超出其父视图的范围,它们仍会显示。但是,事件路由要严格得多。屏幕右侧四分之一的事件永远不会路由到您的视图控制器的视图,因为命中测试在大小错误的 UIViewControllerWrapperView 处失败,其中事件超出了 UIViewControllerWrapperView 的范围。

作为一种解决方法,我将 UITabBarController 子类化,并在 viewWillAppear 中添加以下内容:

@implementation FixedIOS7TabBarController

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    // Fix the frame of the UIViewControllerWrapperView
    self.selectedViewController.view.superview.frame = self.view.bounds;
}

@end

希望对其他人有所帮助....

于 2013-10-07T11:27:36.717 回答
10

正如这个答案中所解释的,

标签栏控制器设置为包含您的视图控制器的容器视图未调整大小以考虑界面处于横向。显示视图控制器时它的尺寸是 768(宽)x 1024(高)。

当 TabBarController 最初以纵向模式显示时,我遇到了这个问题。当设备旋转到横向模式时,右侧的视图没有响应。

该答案中提出的解决方案对我不起作用,因为viewWillAppear:只调用一次。但是,viewDidLayoutSubvews只要视图发生变化(包括旋转)就会被调用,因此我的解决方案是将 UITabBarController 子类化并在以下位置执行解决方法viewDidLayoutSubvews

@implementation FixedIOS7TabBarController

- (void)viewDidLayoutSubviews
{
    // fix for iOS7 bug in UITabBarController
    self.selectedViewController.view.superview.frame = self.view.bounds;
}

@end
于 2013-10-16T15:19:51.810 回答
3

最终在这里找到解决方法:

self.view.autoresizesSubviews = YES;
self.view.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
于 2013-10-04T15:44:42.080 回答
1

正确答案对我不起作用,因为用户可以改变方向;并且在改变方向时在某些区域仍然无法触摸。

所以我创建了自己的解决方案,我不确定这是正常的解决方案。

@implementation FixedIOS7TabBarController
- (UIView*)findInSubview:(UIView*)view className:(NSString*)className
{
    for(UIView* v in view.subviews){
        if([NSStringFromClass(v.class) isEqualToString:className])
            return v;
        UIView* finded = [self findInSubview:v className:className];
        if(finded)
            return finded;
    }
    return nil;
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    UIView* wraperView = [self findInSubview:self.view className:@"UIViewControllerWrapperView"];
    wraperView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
}
@end

非常适合我!

于 2014-01-10T09:38:42.540 回答
0

在左侧的视图控制器列表中导航到受影响的视图/视图控制器,将视图拖到第一响应者下方,使其与视图控制器的视图解除关联。

然后转到右侧的布局选项卡,选择所有 4 个锚点和两组调整大小箭头(水平 + 垂直)。

然后将视图拖回原来的位置(就在视图控制器下方)。

于 2013-10-09T19:03:09.613 回答