是否有可能使用UITableViewStylePlain在UITableView中禁用浮动标题?

我正在使用UITableView来布局内容'页面'。 我使用表视图的标题来布局某些图像等,我宁愿它,如果他们没有浮动,但保持静态,因为他们做样式设置为UITableViewStyleGrouped

其他然后使用UITableViewStyleGrouped ,有没有办法做到这一点? 我想避免使用分组,因为它会在我的所有单元格中添加一个边界,并且需要禁用每个单元格的背景视图。 我想完全控制我的布局。 理想情况下,他们会是一个“UITableViewStyleBareBones”,但我没有看到在文档中的选项…

非常感谢,

您应该能够通过使用自定义单元格来完成此行标题行。 这些将像表格视图中的其他单元一样滚动。

你只需要在你的cellForRowAtIndexPath添加一些逻辑,当它是一个标题行时返回正确的单元格types。

你可能不得不自己pipe理你的部分,也就是把所有东西都放在一个部分中,并伪造头部。 (你也可以尝试返回一个隐藏的视图的标题视图,但我不知道这是否会工作)

一个可能更简单的方法来实现这个:

 CGFloat dummyViewHeight = 40; UIView *dummyView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, self.tableView.bounds.size.width, dummyViewHeight)]; self.tableView.tableHeaderView = dummyView; self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0); 

节标题现在将像任何常规单元格一样滚动。

将表格样式从普通变为分组(由于错误的表格样式,曾经到过这里的人)

警告 :此解决scheme实现了一个保留的API方法。 这可能会阻止该应用程序被Apple批准在AppStore上发布。

我已经描述了在我的博客中浮动部分标题的私有方法

基本上,你只需要UITableView并在其两个方法中返回NO

 - (BOOL)allowsHeaderViewsToFloat; - (BOOL)allowsFooterViewsToFloat; 

好吧,我知道这是晚了,但我必须这样做。 我花了10个小时,现在正在寻找一个工作的解决scheme,但没有find一个完整的答案。 发现了一些提示,但难以让初学者理解。 所以我不得不把我的2美分,并完成答案。

正如已经在less数答案中提出的那样,我能够实现的唯一工作解决scheme是在表视图中插入普通单元格,并将它们作为Section Headers来处理,但实现它的更好方法是将这些单元格插入每一部分的第0行。 这样我们可以很容易地处理这些自定义的非浮动头文件。

所以,步骤是。

  1. 使用样式UITableViewStylePlain实现UITableView。

     -(void) loadView { [super loadView]; UITableView *tblView =[[UITableView alloc] initWithFrame:CGRectMake(0, frame.origin.y, frame.size.width, frame.size.height-44-61-frame.origin.y) style:UITableViewStylePlain]; tblView.delegate=self; tblView.dataSource=self; tblView.tag=2; tblView.backgroundColor=[UIColor clearColor]; tblView.separatorStyle = UITableViewCellSeparatorStyleNone; } 
  2. 像往常一样实现titleForHeaderInSection(你可以通过使用你自己的逻辑来获得这个值,但我更喜欢使用标准委托)。

     - (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section { NSString *headerTitle = [sectionArray objectAtIndex:section]; return headerTitle; } 
  3. 实现像往常一样的数字节点表视图

     - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { int sectionCount = [sectionArray count]; return sectionCount; } 
  4. 照常执行numberOfRowsInSection。

     - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { int rowCount = [[cellArray objectAtIndex:section] count]; return rowCount +1; //+1 for the extra row which we will fake for the Section Header } 
  5. 在heightForHeaderInSection中返回0.0f。

     - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0.0f; } 
  6. 不要实现viewForHeaderInSection。 完全删除该方法而不是返回零。

  7. 在heightForRowAtIndexPath中。 检查是否(indexpath.row == 0)并返回节标题所需的单元格高度,否则返回单元格的高度。

     - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { if(indexPath.row == 0) { return 80; //Height for the section header } else { return 70; //Height for the normal cell } } 
  8. 现在在cellForRowAtIndexPath中,检查是否(indexpath.row == 0),并按照您想要的节标题实现该单元格,并将select样式设置为none。 ELSE实现这个单元格就像你想要的正常单元格一样。

     - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SectionCell"]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"SectionCell"] autorelease]; cell.selectionStyle = UITableViewCellSelectionStyleNone; //So that the section header does not appear selected cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SectionHeaderBackground"]]; } cell.textLabel.text = [tableView.dataSource tableView:tableView titleForHeaderInSection:indexPath.section]; return cell; } else { UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"Cell"] autorelease]; cell.selectionStyle = UITableViewCellSelectionStyleGray; //So that the normal cell looks selected cell.backgroundView =[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"CellBackground"]]autorelease]; cell.selectedBackgroundView=[[[UIImageView alloc] initWithImage:[UIImage imageNamed:@"SelectedCellBackground"]] autorelease]; } cell.textLabel.text = [[cellArray objectAtIndex:indexPath.section] objectAtIndex:indexPath.row -1]; //row -1 to compensate for the extra header row return cell; } } 
  9. 现在实现willSelectRowAtIndexPath,如果indexpath.row == 0,则返回nil。这将关心didSelectRowAtIndexPath永远不会被触发的节标题行。

     - (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { return nil; } return indexPath; } 
  10. 最后在didSelectRowAtIndexPath中,检查if(indexpath.row!= 0)并继续。

     - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row != 0) { int row = indexPath.row -1; //Now use 'row' in place of indexPath.row //Do what ever you want the selection to perform } } 

这样你就完成了。 你现在有一个完美的滚动,非浮动部分标题。

在你的Interface Builder中点击你的问题表视图

问题表视图

然后导航到“属性”检查器,并将“样式平铺”更改为“分组”;

简单

关于UITableViewStyleGrouped有趣的是,tableView将样式添加到单元格而不是TableView。

样式作为一个名为UIGroupTableViewCellBackground的类作为backgroundView添加到单元格中,该类根据该部分中单元格的位置处理绘制不同的背景。

所以一个非常简单的解决scheme将是使用UITableViewStyleGrouped,将表的backgroundColor设置为clearColor,并且简单地replacecellForRow中单元格的backgroundView:

 cell.backgroundView = [[[UIView alloc] initWithFrame:cell.bounds] autorelease]; 

改变你的TableView风格:

 self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped]; 

根据UITableView的苹果文档:

UITableViewStylePlain-一个普通的表格视图。 任何节标题或页脚显示为行内分隔符,并在滚动表视图时浮动。

UITableViewStyleGrouped – 一个表视图,其各节显示不同的行组。 部分页眉和页脚不会浮动。

希望这个小小的改变会帮助你..

还有一个棘手的方法。 其主要思想是将节号加倍,第一个只显示headerView,第二个显示真实单元。

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return sectionCount * 2; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section%2 == 0) { return 0; } return _rowCount; } 

那么需要做的是实现headerInSection委托:

 - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { if (section%2 == 0) { //return headerview; } return nil; } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { if (section%2 == 0) { //return headerheight; } return 0; } 

这种方法对您的数据源也没有什么影响:

 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { int real_section = (int)indexPath.section / 2; //your code } 

与其他方法相比,这种方法是安全的,而不改变tableview的框架或contentInsets。 希望这可能有帮助。

得到你想要的最简单的方法是将你的表格样式设置为UITableViewStyleGrouped ,分隔符样式为UITableViewCellSeparatorStyleNone

 - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { return CGFLOAT_MIN; // return 0.01f; would work same } - (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { return [[UIView alloc] initWithFrame:CGRectZero]; } 

不要尝试返回页脚视图nil ,不要忘记设置标题的高度和标题视图,你必须得到你想要的。

虽然这可能不能解决你的问题,但是当我想要做类似的事情时,这个事情就是为我做的。 而不是设置标题,我使用了上面部分的页脚。 救了我的是,这个部分本质上是小而静的,所以它从来没有滚动到视图的底部。

在思考如何解决这个问题时,我想起了关于UITableViewStyleGrouped的一个非常重要的细节。 UITableView实现分组样式(单元格四舍五入的边框)的方法是将自定义backgroundView添加到UITableViewCells,而不是UITableView。 每个单元格根据其在部分中的位置添加一个backgroundView(上部的行获取部分边界的上部,中间的部分获得侧边界,底部获得 – 下面的部分)。 所以,如果我们只是想要一个简单的风格,而我们没有一个自定义的backgroundView(这是90%的时间),那么我们需要做的就是使用UITableViewStyleGrouped,并删除自定义背景。 这可以通过以下两个步骤完成:

将我们的tableView样式更改为UITableViewStyleGrouped在我们返回单元格之前,将以下行添加到cellForRow:

cell.backgroundView = [[[UIView] initWithFrame:cell.bounds] autorelease];

就是这样。 tableView风格将变成完全像UITableViewStylePlain,除了浮动标题。

希望这可以帮助!

另一种方法是在你想要的标题之前创build一个空白部分,并将标题放在该部分。 由于该部分是空的,标题将立即滚动。

你可以在上面添加一个Section(零行),然后将上面的SectionFooterView设置为当前节的headerView,footerView不会浮动。 希望它能提供帮助。

忽略XAK。 如果您希望自己的应用有机会被苹果接受,请不要探索任何私人方法。

如果您使用Interface Builder,这是最简单的。 你会添加一个UIView在视图的顶部(图像将去),然后在下面添加你的tableview。 IB应该相应地resize; 也就是说,tableview的顶部会触及刚添加的UIView的底部,它的高度覆盖了屏幕的其余部分。

这里的想法是,如果该UIView实际上不是表视图的一部分,它将不会随着tableview的滚动。 即忽略tableview标题。

如果你不使用接口生成器,那么它会更复杂一点,因为你必须得到tableview的位置和高度。

这可以通过在UITableViewController的viewDidLoad方法中手动分配标题视图来实现,而不是使用委托的viewForHeaderInSection和heightForHeaderInSection。 例如在你的UITableViewController的子类中,你可以这样做:

 - (void)viewDidLoad { [super viewDidLoad]; UILabel *headerView = [[UILabel alloc] initWithFrame:CGRectMake(0, 0, 0, 40)]; [headerView setBackgroundColor:[UIColor magentaColor]]; [headerView setTextAlignment:NSTextAlignmentCenter]; [headerView setText:@"Hello World"]; [[self tableView] setTableHeaderView:headerView]; } 

当用户滚动时,标题视图将消失。 我不知道这是为什么这样工作,但它似乎达到你想要做的。

检查如何使用StoryBoard实现标题的答案:StoryBoards中的表标题视图

另外请注意,如果你不执行

 viewForHeaderInSection:(NSInteger)section 

它不会漂浮,这正是你想要的。

要完全删除浮动部分的标题部分,可以这样做:

 - (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { return [[UIView alloc] init]; } 

return nil不起作用。

要禁用浮动,但仍然显示节标题,您可以提供具有自己的行为的自定义视图。

也许你可以在tableView上使用scrollViewDidScroll ,并根据当前可见的标题更改contentInset

这似乎为我的用例工作!

 extension ViewController : UIScrollViewDelegate{ func scrollViewDidScroll(_ scrollView: UIScrollView) { guard let tableView = scrollView as? UITableView, let visible = tableView.indexPathsForVisibleRows, let first = visible.first else { return } let headerHeight = tableView.rectForHeader(inSection: first.section).size.height let offset = max(min(0, -tableView.contentOffset.y), -headerHeight) self.tableView.contentInset = UIEdgeInsetsMake(offset, 0, -offset, 0) } } 

对于Swift 3+

只需使用UITableViewStyleGrouped并将页脚的高度设置为零,如下所示:

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

也许你可以简单地使标题视图背景透明:

 - (void)tableView:(UITableView *)tableView willDisplayHeaderView:(UIView *)view forSection:(NSInteger)section { view.tintColor = [UIColor clearColor]; } 

或者全球应用:

  [UITableViewHeaderFooterView appearance].tintColor = [UIColor clearColor]; 

我有另一个更简单的解决scheme,使用没有自动布局和一切通过XIB完成:

1 /把你的头在桌面视图拖放它直接在tableview。

2 /在新制作的标题的大小检查器中,只需更改其自动大小:您应该只留下顶部,左侧和右侧的锚点以及水平填充。

这就是它应该如何设置标题

这应该够了吧 !

你可以通过在tableview委托类中实现viewForHeaderInSection方法来轻松实现。 这个方法需要一个UIView作为返回对象(这是你的标题视图)。 我在我的代码中做了同样的事情