为什么在iOS7的UITableViewStyleGrouped风格的UITableView的顶部有额外的填充

从iOS7开始,在我的UITableView的顶部有一个额外的空间,它有一个样式UITableViewStyleGrouped

这里是一个例子:

在这里输入图像描述

tableview从第一个箭头开始,有35个像素的不明原因的填充,然后绿色的头是由viewForHeaderInSection (其中部分为0)返回的UIView

任何人都可以解释这35像素的数量来自哪里,我怎么能摆脱它,而不切换到UITableViewStylePlain

我得到以下帮助:

YouStoryboard.storyboard> YouViewController>属性检查器>取消选中 – 调整滚动视图插图。

在这里输入图像描述

我玩了更多,似乎这是设置tableView的tableHeaderView = nil的副作用。

因为我的tableView有一个dynamic的出现tableHeaderView ,当我需要隐藏tableHeaderView ,而不是做self.tableView.tableHeaderView = nil; , 我做:

 self.tableView.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.tableView.bounds.size.width, 0.01f)]; 

我喜欢这个解决scheme比设置一个有点任意的contentInset.top因为我contentInset.topdynamic地使用contentInset.top 。 不得不记住,每当我重新计算contentInset.top时,删除额外的35px是乏味的。

对于IOS 7,如果你正在视图控制器中分配一个tableview,你可以看看

 self.edgesForExtendedLayout = UIRectEdgeNone; 

你的问题和我的似乎很相似

更新:

Swift的iOS 9.x:

 self.edgesForExtendedLayout = UIRectEdge.None 

Swift 3:

 self.edgesForExtendedLayout = UIRectEdge.init(rawValue: 0) 

尝试更改UITableViewUIScrollViewinheritance的contentInset属性。

 self.tableView.contentInset = UIEdgeInsetsMake(-36, 0, 0, 0); 

这是一个解决方法,但它的工作原理

 self.automaticallyAdjustsScrollViewInsets = NO; 

尝试,你可以处理它!

您可以检测到您的应用程序是否运行iOS7或更高版本,并在您的表视图委托中添加这两个方法(通常在您的UIViewController代码中)

 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return CGFLOAT_MIN; } -(CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return CGFLOAT_MIN; } 

这可能不是一个优雅的解决scheme,但为我工作

取消选中“调整滚动查看插图”

在这里输入图像描述

我find了我原来的错误的原因,并创build了一个示例项目展示它。 我相信有一个iOS7的错误。

从iOS7开始,如果使用分组样式创buildUITableView,但没有在第一个布局上设置委托,那么您设置委托并调用reloadData,顶部将会有一个永远不会消失的35像素的空间。

看到这个项目,我展示了这个bug: https : //github.com/esilverberg/TableViewDelayedDelegateBug

特别是这个文件: https : //github.com/esilverberg/TableViewDelayedDelegateBug/blob/master/TableViewDelayedDelegateBug/ViewController.m

如果第24行被激活,

 [self performSelector:@selector(updateDelegate) withObject:nil afterDelay:0.0]; 

顶部会有一个额外的35像素的空间。 如果第27行被激活,24被注释掉,

 self.tableView.delegate = self; 

顶部没有空间。 这就像tableViewcaching结果的地方,而不是在委托设置和reloadData被调用后重绘自己。

另一个快速的评论…即使在XCode 6.1,有一个垂直空间出现在UIScrollViewsUITextViewsUITableViews顶部的错误。

在这里输入图像描述

有时,解决这个问题的唯一方法是进入故事板并拖动问题控件,使其不再是页面上的第一个子视图。

在这里输入图像描述

(感谢Oded指出我在这个方向上……我发表了这个评论,只是为了添加一些截图,来演示症状和修复。)

根据Apple 针对iOS7的转换指南 ,滚动视图的内容插入会自动进行调整。 automaticallyAdjustsScrollViewInsets的默认值被设置为YES。

具有UITableView的UIViewController应将此属性设置为NO。

 self.automaticallyAdjustsScrollViewInsets = NO; 

这将做的伎俩。

编辑1:

另外,可以尝试 –

 self.navigationController.navigationBar.translucent = YES; 

这也删除了顶部的额外填充。

在使用分组的TableView时,使用这个来避免在viewWillAppear中边界切割

 self.tableView.contentInset = UIEdgeInsetsMake(-35, 0, 0, 0); 

故事板:

只需取消选中:在View Controller的选项中Adjust Scroll View Insets

在这里输入图像描述

码:

 self.automaticallyAdjustsScrollViewInsets = false 

上面的很多回答太hacky。 如果苹果决定解决这个意外的行为,他们将在未来的任何时候突破。

问题的根源:

  1. 一个UITableView不喜欢有一个高度为0.0的标题。 如果你想要做的是有一个高度为0的标题,你可以跳转到解决scheme。

  2. 即使稍后将一个非0.0高度分配给您的头文件, UITableView也不喜欢先分配一个高度为0.0的头文件。

解:

然后,最简单可靠的解决方法是确保您的标题高度不是0时,将其分配给您的表视图。

像这样的东西可以工作:

 // Replace UIView with whatever class you're using as your header below: UIView *tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, self.tableView.bounds.size.width, CGFLOAT_MIN)]; self.tableView.tableHeaderView = tableViewHeaderView; 

像这样的事情在某个时候会导致问题(通常在滚动之后):

 // Replace UIView with whatever class you're using as your header below: UIView *tableViewHeaderView = [[UIView alloc] initWithFrame:CGRectZero]; self.tableView.tableHeaderView = tableViewHeaderView; 

在我的情况下,这是对我的帮助。 我也支持ios6。

 if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7) { self.edgesForExtendedLayout = UIRectEdgeNone; self.extendedLayoutIncludesOpaqueBars = NO; self.automaticallyAdjustsScrollViewInsets = NO; } 

只需将以下内容添加到VC中的viewDidLoad:

 self.automaticallyAdjustsScrollViewInsets = NO; 

Swift:iOS我有滚动视图上的tableview ..当我点击“返回”在同一屏幕上。 滚动视图上占用更多的空间..解决这个我用过:

  self.automaticallyAdjustsScrollViewInsets = false 

一个布尔值,指示视图控制器是否应该自动调整其滚动视图插图。 默认值为true,允许视图控制器根据状态栏,导航栏和工具栏或选项卡栏使用的屏幕区域来调整其滚动视图插图。 如果您想自己pipe理滚动视图插入调整,例如当视图层次结构中有多个滚动视图时,则设置为false。

我的答案将是更一般的答案,但也可以应用于此。

如果( ViewController的根视图根视图第一个子视图(子视图)是UIScrollView(或UIScrollView本身)的子类,并且if

 self.navigationController.navigationBar.translucent = YES; 

框架会自动设置预先计算的contentInset


为了避免这个,你可以做

 self.automaticallyAdjustsScrollViewInsets = NO; 

但在我的情况下,我无法做到这一点,因为我正在实施SDK,其中有UIView组件,可供其他开发人员使用。 该UIView组件包含UIWebView(其中有UIScrollView作为第一个子视图)。 如果该组件被添加为UIViewController视图层次结构中的第一个子项,则系统将自动应用insets。

我已经通过在添加UIWebView之前添加虚框视图(0,0,0,0)来解决这个问题。

在这种情况下,系统没有findUIScrollView的子类作为第一个子视图,也没有应用插入

感谢@Aurelien Porte的回答。 这是我的解决scheme

这个问题的原因: –

  1. 一个UITableView不喜欢有一个高度为0.0的标题。 如果你想要做的是有一个高度为0的标题,你可以跳转到解决scheme。
  2. 即使稍后将一个非0.0高度分配给您的头文件,UITableView也不喜欢先分配一个高度为0.0的头文件。

在ViewDidLoad中: –

 self.edgesForExtendedLayout = UIRectEdge.None self.automaticallyAdjustsScrollViewInsets = false 

不需要像这样的东西: –

 self.myTableview.contentInset = UIEdgeInsetsMake(-56, 0, 0, 0) 

heightForHeaderInSection委托中: –

 if section == 0 { return 1 } else { return 40; // your other headers height value } 

viewForHeaderInSection委托中: –

 if section == 0 { // Note CGFloat.min for swift // For Objective-c CGFLOAT_MIN let headerView = UIView.init(frame: CGRectMake(0.0, 0.0, self.myShaadiTableview.bounds.size.width, CGFloat.min)) return headerView } else { // Construct your other headers here } 

所以我在这里尝试了所有的方法,而这次他们都没有帮助。 我的情况是在iOS 9上分组的表格视图。我不知道为什么,怎么find这个,但是对于我来说,设置一个至less有0.01高度的UIViewtableViewHeader出来了。 CGRectZero没有帮助,没有什么帮助:

 tableView.tableHeaderView = UIView(frame: CGRect(x: 0.0, y: 0.0, width: 0.0, height: 0.01)) 

这是使用Swift 3的iOS 10的解决scheme:

您可以通过从UITableViewDelegate实现以下方法来摆脱顶部和底部的填充。

  func tableView( _ tableView: UITableView, heightForHeaderInSection section: Int ) -> CGFloat { return CGFloat.leastNormalMagnitude } func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { return CGFloat.leastNormalMagnitude } 

我假设这只是新的UITableViewStyleGrouped样式的一部分。 这是在所有分组表格的意见,似乎没有任何直接的方式来控制这个空间。

如果这个空间是由一个UIView表示的,那么可以searchUITableView所有subviews来find这个特定的视图并直接编辑它。 然而,在标题和单元格开始之前,这个空间也可能只是一个硬编码的偏移量,并且没有任何方法可以编辑它。

要search所有的子视图(当表格没有单元格时,我会运行这个代码,以使它更容易读取输出):

 - (void)listSubviewsOfView:(UIView *)view { // Get the subviews of the view NSArray *subviews = [view subviews]; // Return if there are no subviews if ([subviews count] == 0) return; for (UIView *subview in subviews) { NSLog(@"%@", subview); // List the subviews of subview [self listSubviewsOfView:subview]; } } 

我有和arielyz一样的解决方法。 一旦我移动UITableView不是父视图的第一个子视图,它就消失了。 我的空间是20像素,而不是35。

我不能在一个肖像xib,只有一个景观xib重新创build它。 如果我可以在一个简单的演示应用程序中重现它,我会稍后提交一个雷达错误。

我认为使UIEdgeInsets -35 0 0 0是单调乏味的。 在我的情况下,我实现了tableView:heightForHeaderInSection:方法,它有可能返回0。

当我改变0到0.1f时,问题就消失了。

使用这一个我认为这有助于… … –

  - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0.005f;// set this according to that you want... } 
 override func viewWillAppear(animated: Bool) { self.edgesForExtendedLayout = UIRectEdge.None // OR self.sampleTableView.contentInset = UIEdgeInsetsMake(-64, 0, 0, 0); //OR self.automaticallyAdjustsScrollViewInsets = false } 
 -(CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return CGFLOAT_MIN; } 

这就是所有人!

我也一直在抨击这个问题。 很确定这是一个iOS7的错误。 最终帮助我的是xib中的观点顺序。 我有一个视图正确显示表视图,另一个表视图有额外的35px空间。 (UITableView明智)之间的唯一区别是,在不良显示视图UITableView是第一个孩子,而在正确显示的视图,这是第二个。

这对我来说只是改变视图的顺序。 我真的不希望为解决方法添加额外的代码行…

我们有多个答案。

1)你可以添加UIImageview视图didload

 UIImageView * imbBackground = [UIImageView new]; [self.view addSubview:imbBackground]; 

2)您可以设置页眉和页脚高度0.1

 - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return 0.1; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{ return 0.1; } 

3)您可以添加高度为0.1的页眉和页脚视图

 tblCampaigns.tableHeaderView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tblCampaigns.bounds.size.width, 0.01f)]; tblCampaigns.tableFooterView = [[UIView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, tblCampaigns.bounds.size.width, 0.01f)]; 

只需在视图的绝对顶部固定你的tableview(或者开始)。 额外的不需要的空间恰好是导航栏的高度。

下面做的(Swift)解决了这个问题, 但是当你不需要头部的时候,这个工作就可以解决。

 func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { return CGFloat.min } 

如果你这样做,你将不得不放弃第一部分,并使用其他的内容。

UITableViewDataSource实现:

 func numberOfSectionsInTableView(tableView: UITableView) -> Int { return <number_of_data_sections>+1 } func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { // the first section we don't use for data if section == 0 { return 0 } // starting from 1, there are sections we use if section == 1 { let dataSection = section - 1 // use dataSection for your content (useful, when data provided by fetched result controller). For example: if let sectionInfo = myFRC!.sections![dataSection] as? NSFetchedResultsSectionInfo { return sectionInfo.numberOfObjects } } return 0 } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let dataIndexPath = NSIndexPath(forRow: indexPath.row, inSection: (indexPath.section - 1) ) // return cell using transformed dataIndexPath } func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat { if section == 1 { // return your header height } return CGFloat.min } func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { if section == 1 { // return your header view } return nil } func tableView(tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { // in my case, even when 1st section header was of zero heigh, I saw the space, an that was a footer. I did not need footer at all, so always gave zero height return CGFloat.min } 

就是这样。 模型不知道变化的任何内容,因为我们在访问数据时转换段号。