iOS 7表视图无法自动调整内容插入

时间:2013-09-30 10:21:15

标签: iphone objective-c uitableview ios7

我正在将我的项目转移到iOS7。我正面临着与半透明导航栏相关的奇怪问题。

我有一个视图控制器,它有一个tableview作为子视图(让我们称之为ControllerA)。我使用controllerA初始化一个新的uinavigationcontroller并使用presentviewcontroller以模态方式呈现它。导航栏会阻止显示的视图控制器的表视图。我将 automaticAdjustsScrollViewInsets 设置为 YES ,但结果没有改变。 我知道我可以将 edgesForExtendedLayout 设置为 UIRectEdgeNone ,但它会使导航栏不再是半透明的。

Table view get blocked

之后,我尝试创建一个新的视图控制器进行测试。它包含几乎相同的元素。但结果却大相径庭。表视图内容不会被阻止。

enter image description here

结论

  1. 两个视图控制器'automaticAdjustsScrollViewInsets设置为YES
  2. 该项目未使用故事板
  3. 第一个是在Xcode 4.6上创建的,第二个是在Xcode 5上新创建的
  4. 我比较了两个类xib和代码,没有太多不同

7 个答案:

答案 0 :(得分:55)

我在苹果开发者论坛上找到了答案。 有两种不同的情况。

第一个,添加的视图控制器是UITableViewController。 并且问题不应该出现,因为苹果会自动填充它。

第二个,视图控制器不是UITableViewController。 在视图层次结构中,它包含一个UITableView。在这种情况下,如果UITableview(或ScrollView)是viewController的主视图或主视图的第一个子视图,它将起作用。否则,视图控制器不知道要填充哪个滚动视图,它将发生问题。

在我的例子中,视图控制器是第二个。并且有一个背景图像视图作为主视图的第一个子视图。所以,它失败了。

以下是Apple开发者论坛链接(需要开发者帐户才能访问): https://devforums.apple.com/message/900138#900138

答案 1 :(得分:47)

如果您希望视图低于导航栏,但也希望它定位,以便默认情况下滚动视图内容的顶部位于导航栏下方,您可以在布局视图后手动添加顶部插入。这实际上是顶层视图是滚动视图时视图布局系统的作用。

-(void)viewDidLayoutSubviews {
    if ([self respondsToSelector:@selector(topLayoutGuide)]) {
        UIEdgeInsets currentInsets = self.scrollView.contentInset;
        self.scrollView.contentInset = (UIEdgeInsets){
            .top = self.topLayoutGuide.length,
            .bottom = currentInsets.bottom,
            .left = currentInsets.left,
            .right = currentInsets.right
        };
    }
}

答案 2 :(得分:3)

根据Tony的回答,我能够以编程方式解决此问题,暂时将表格视图发送到后面,进行调整,然后将背景视图发送回后面。在我的情况下,这种方法没有闪烁。

在视图控制器中:


- (void)viewWillLayoutSubviews {
    [super viewWillLayoutSubviews];

    [self.view sendSubviewToBack:self.tableView];
}

- (void)viewDidLayoutSubviews {
    [super viewDidLayoutSubviews];

    [self.view sendSubviewToBack:self.backgroundView];
}

显然,如果self.view上还有其他子视图,您可能还需要对其进行重新排序。

答案 3 :(得分:2)

对此已经有太多的答案了,但是我必须采用Christopher的解决方案并稍微修改它以支持调整的视图,允许在{{1的子类中更改内容插入}}

UIViewController

解释一下:

@interface MyViewController () @property (weak, nonatomic) IBOutlet UIScrollView *scrollView; @property (assign, nonatomic) UIEdgeInsets scrollViewInitialContentInset; @end @implementation MyViewController - (void)viewDidLoad { [super viewDidLoad]; [self setScrollViewInitialContentInset:UIEdgeInsetsZero]; } - (void)viewWillLayoutSubviews { [super viewWillLayoutSubviews]; if (UIEdgeInsetsEqualToEdgeInsets([self scrollViewInitialContentInset], UIEdgeInsetsZero)) { [self setScrollViewInitialContentInset:[self.scrollView contentInset]]; } } - (void)viewDidLayoutSubviews { [super viewDidLayoutSubviews]; UIEdgeInsets scrollViewInset = [self scrollViewInitialContentInset]; if (UIEdgeInsetsEqualToEdgeInsets(scrollViewInset, UIEdgeInsetsZero) { if ([self respondsToSelector:@selector(topLayoutGuide)]) { scrollViewInset.top = [self.topLayoutGuide length]; } if ([self respondsToSelector:@selector(bottomLayoutGuide)]) { scrollViewInset.bottom = [self.bottomLayoutGuide length]; } [self.scrollView setContentInset:scrollViewInset]; } } @end 的任何子类现在都可以修改MyViewControllercontentInset的{​​{1}},并且会受到尊重。但是,如果scrollView的{​​{1}}为viewDidLoad:它将展开为contentInsetscrollView

答案 4 :(得分:1)

Swift 2 中的@Christopher Pickslay解决方案:

override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    let topInset = topLayoutGuide.length
    inTableView.contentInset.top = topInset
    inTableView.contentOffset.y = -topInset
    inTableView.scrollIndicatorInsets.top = topInset
}

答案 5 :(得分:0)

是的 - 有点烦人。

我在主视图中有一个带有单个tableview的笔尖,而不是使用autolayout。有一个标签栏,导航栏和状态栏,应用程序需要恢复到5.0。在“界面”构建器中,整齐地“在iOS7和iOS6.1中并排查看它”可以正常工作,显示表格整齐(一旦iOS6 / 7增量设置正确)。

然而,在设备或模拟器上运行时,表顶部有一个很大的间隙,这是由于内容插入(几乎与iOS6 / 7垂直增量相匹配)的结果在笔尖。

我得到的解决方案是在viewWillAppear中输入[_tableView setContentInset:UIEdgeInsetsZero]。

另一个丑陋的黑客,屏幕上有漂亮的结果......

答案 6 :(得分:-5)

[self.navigationController setNavigationBarHidden:YES animated:YES]; 

在:

- (void)viewDidLoad