ios 是否可以使用 UITableViewStylePlain 在 UITableView 中禁用浮动标题?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1074006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is it possible to disable floating headers in UITableView with UITableViewStylePlain?
提问by Tricky
I'm using a UITableView
to layout content 'pages'. I'm using the headers of the table view to layout certain images etc. and I'd prefer it if they didn't float but stayed static as they do when the style is set to UITableViewStyleGrouped
.
我正在使用 aUITableView
来布局内容“页面”。我正在使用表格视图的标题来布局某些图像等,如果它们不浮动但像样式设置为UITableViewStyleGrouped
.
Other then using UITableViewStyleGrouped
, is there a way to do this? I'd like to avoid using grouped as it adds a margin down all my cells and requires disabling of the background view for each of the cells. I'd like full control of my layout. Ideally they'd be a "UITableViewStyleBareBones", but I didn't see that option in the docs...
其他然后使用UITableViewStyleGrouped
,有没有办法做到这一点?我想避免使用分组,因为它会为我的所有单元格添加一个边距,并且需要禁用每个单元格的背景视图。我想完全控制我的布局。理想情况下,它们是“UITableViewStyleBareBones”,但我在文档中没有看到该选项...
Many thanks,
非常感谢,
采纳答案by frankodwyer
You should be able to fake this by using a custom cell to do your header rows. These will then scroll like any other cell in the table view.
您应该能够通过使用自定义单元格来制作标题行来伪造这一点。然后这些将像表格视图中的任何其他单元格一样滚动。
You just need to add some logic in your cellForRowAtIndexPath
to return the right cell type when it is a header row.
您只需要在您cellForRowAtIndexPath
的标题行中添加一些逻辑即可返回正确的单元格类型。
You'll probably have to manage your sections yourself though, i.e. have everything in one section and fake the headers. (You could also try returning a hidden view for the header view, but I don't know if that will work)
不过,您可能必须自己管理您的部分,即在一个部分中包含所有内容并伪造标题。(您也可以尝试返回标题视图的隐藏视图,但我不知道这是否可行)
回答by samvermette
A probably easier way to achieve this:
一种可能更简单的方法来实现这一目标:
Objective-C:
目标-C:
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);
Swift:
迅速:
let dummyViewHeight = CGFloat(40)
self.tableView.tableHeaderView = UIView(frame: CGRect(x: 0, y: 0, width: self.tableView.bounds.size.width, height: dummyViewHeight))
self.tableView.contentInset = UIEdgeInsetsMake(-dummyViewHeight, 0, 0, 0)
Section headers will now scroll just like any regular cell.
部分标题现在将像任何常规单元格一样滚动。
回答by david72
(For who ever got here due to wrong table style) Change Table style from plain to grouped, via the attributes inspector, or via code:
(对于由于表格样式错误而来到这里的人)通过属性检查器或通过代码将表格样式从普通更改为分组:
let tableView = UITableView(frame: .zero, style: .grouped)
回答by Tricky
WARNING: this solution implements a reserved API method. This could prevent the app from being approved by Apple for distribution on the AppStore.
警告:此解决方案实现了保留的 API 方法。这可能会阻止 Apple 批准该应用程序在 AppStore 上分发。
I've described the private methods that turns of section headers floating in my blog
我已经描述了在我的博客中浮动节标题的私有方法
Basically, you just need to subclass UITableView
and return NO
in two of its methods:
基本上,您只需要子类化UITableView
并返回NO
它的两个方法:
- (BOOL)allowsHeaderViewsToFloat;
- (BOOL)allowsFooterViewsToFloat;
回答by Sumit Anantwar
Ok, i know it is late but i had to do it. I have spent 10 hours by now searching for a working solution but did not find a complete answer. Did found some hints but difficult for starters to understand. So i had to put in my 2 cents and complete the answer.
好吧,我知道已经晚了,但我必须这样做。到目前为止,我已经花了 10 个小时寻找有效的解决方案,但没有找到完整的答案。确实找到了一些提示,但初学者很难理解。所以我不得不投入我的 2 美分并完成答案。
As it has been suggested in the few of the answers the only working solution that i was able to implement is by inserting normal cells in the table view and handle them as Section Headers, but the better way to achieve it is by inserting these cells at row 0 of every section. This way we can handle these custom non-floating headers very easily.
正如在少数几个答案中所建议的,我能够实现的唯一可行解决方案是在表格视图中插入普通单元格并将它们作为节标题处理,但实现它的更好方法是将这些单元格插入到每个部分的第 0 行。这样我们就可以很容易地处理这些自定义的非浮动标题。
So, the steps are.
所以,步骤是。
Implement UITableView with style UITableViewStylePlain.
-(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; }
Implement titleForHeaderInSection as usual ( you can get this value by using your own logic, but I prefer to use standard delegates ).
- (NSString *)tableView: (UITableView *)tableView titleForHeaderInSection:(NSInteger)section { NSString *headerTitle = [sectionArray objectAtIndex:section]; return headerTitle; }
Immplement numberOfSectionsInTableView as usual
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { int sectionCount = [sectionArray count]; return sectionCount; }
Implement numberOfRowsInSection as usual.
- (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 }
Return 0.0f in heightForHeaderInSection.
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { return 0.0f; }
DO NOT implement viewForHeaderInSection. Remove the method completely instead of returning nil.
In heightForRowAtIndexPath. Check if(indexpath.row == 0) and return the desired cell height for the section header, else return the height of the cell.
- (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 } }
Now in cellForRowAtIndexPath, check if(indexpath.row == 0) and implement the cell as you want the section header to be and set the selection style to none. ELSE implement the cell as you want the normal cell to be.
- (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; } }
Now implement willSelectRowAtIndexPath and return nil if indexpath.row == 0. This will care that didSelectRowAtIndexPath never gets fired for the Section header row.
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.row == 0) { return nil; } return indexPath; }
And finally in didSelectRowAtIndexPath, check if(indexpath.row != 0) and proceed.
- (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 } }
使用 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; }
像往常一样实现 numberOfSectionsInTableView
- (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。完全删除该方法而不是返回 nil。
在 heightForRowAtIndexPath 中。检查 if(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 中,检查 if(indexpath.row == 0) 并按照您希望的部分标题实现单元格并将选择样式设置为无。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 永远不会为 Section 标题行触发。
- (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 } }
With this you are done. You now have a perfectly scrolling, non-floating section header.
有了这个,你就完成了。您现在拥有一个完美滚动的非浮动节标题。
回答by HannahCarney
回答by adamsiton
The interesting thing about UITableViewStyleGrouped is that the tableView adds the style to the cellsand not to the TableView.
UITableViewStyleGrouped 的有趣之处在于 tableView 将样式添加到单元格而不是 TableView。
The style is added as backgroundView to the cells as a class called UIGroupTableViewCellBackground which handles drawing different background according to the position of the cell in the section.
该样式作为背景视图添加到单元格中,作为一个名为 UIGroupTableViewCellBackground 的类,该类根据单元格在该部分中的位置处理绘制不同的背景。
So a very simple solution will be to use UITableViewStyleGrouped, set the backgroundColor of the table to clearColor, and simply replace the backgroundView of the cell in cellForRow:
因此,一个非常简单的解决方案是使用 UITableViewStyleGrouped,将表格的 backgroundColor 设置为 clearColor,然后简单地替换 cellForRow 中单元格的 backgroundView:
cell.backgroundView = [[[UIView alloc] initWithFrame:cell.bounds] autorelease];
回答by Aks
Change your TableView Style:
更改您的 TableView 样式:
self.tableview = [[UITableView alloc] initwithFrame:frame style:UITableViewStyleGrouped];
As per apple documentation for UITableView:
根据 UITableView 的苹果文档:
UITableViewStylePlain- A plain table view. Any section headers or footers are displayed as inline separators and float when the table view is scrolled.
UITableViewStyleGrouped- A table view whose sections present distinct groups of rows. The section headers and footers do not float.
UITableViewStylePlain - 一个普通的表格视图。任何部分的页眉或页脚都显示为行内分隔符,并在滚动表格视图时浮动。
UITableViewStyleGrouped- 一个表视图,其部分呈现不同的行组。节页眉和页脚不浮动。
回答by Lane
There is another tricky way. The main idea is to double the section number, and first one only shows the headerView while the second one shows the real cells.
还有另一种棘手的方法。主要思想是将部分编号加倍,第一个只显示 headerView,而第二个显示真实的单元格。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return sectionCount * 2;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if (section%2 == 0) {
return 0;
}
return _rowCount;
}
What need to do then is to implement the headerInSection delegates:
然后需要做的是实现 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;
}
This approach also has little impact on your datasources:
这种方法对您的数据源也几乎没有影响:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
int real_section = (int)indexPath.section / 2;
//your code
}
Comparing with other approaches, this way is safe while not changing the frame or contentInsets of the tableview. Hope this may help.
与其他方法相比,这种方式是安全的,同时不会改变 tableview 的 frame 或 contentInsets。希望这可能会有所帮助。
回答by Michail Pidgorodetskiy
The easiest way to get what you want is set your table style as UITableViewStyleGrouped
,
separator style as UITableViewCellSeparatorStyleNone
:
获得所需内容的最简单方法是将表格样式设置为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];
}
Do not try return footer view as nil
, don't forget set header height and header view, after you must get what you desired.
不要尝试将页脚视图返回为nil
,不要忘记设置页眉高度和页眉视图,之后您必须获得所需的内容。