是否有可能使用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行。 这样我们可以很容易地处理这些自定义的非浮动头文件。
所以,步骤是。
-
使用样式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; }
-
像往常一样实现titleForHeaderInSection(你可以通过使用你自己的逻辑来获得这个值,但我更喜欢使用标准委托)。
- (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section { NSString *headerTitle = [sectionArray objectAtIndex:section]; return headerTitle; }
-
实现像往常一样的数字节点表视图
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { int sectionCount = [sectionArray count]; return sectionCount; }
-
照常执行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 }
-
在heightForHeaderInSection中返回0.0f。
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0.0f; }
-
不要实现viewForHeaderInSection。 完全删除该方法而不是返回零。
-
在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 } }
-
现在在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; } }
-
现在实现willSelectRowAtIndexPath,如果indexpath.row == 0,则返回nil。这将关心didSelectRowAtIndexPath永远不会被触发的节标题行。
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { return nil; } return indexPath; }
-
最后在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作为返回对象(这是你的标题视图)。 我在我的代码中做了同样的事情