ios 静态和动态单元格的 UITableView 混合?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18153702/
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
UITableView Mix of Static and Dynamic Cells?
提问by Josh Kahane
I know you cannot mix Static and Dynamic cell types in a single UITableView
but I couldn't think of a better way to describe my issue.
我知道您不能将静态和动态单元格类型混合在一起,UITableView
但我想不出更好的方法来描述我的问题。
I have several predetermined cells with fixed content, I also have an unknown number of cells with dynamic content which sits in the middle. So I want to my table to look something like this:
我有几个具有固定内容的预定单元格,我还有未知数量的具有动态内容的单元格位于中间。所以我想让我的桌子看起来像这样:
Fixed
Fixed
Fixed
Dynamic
Dynamic
Dynamic
Dynamic
Dynamic
Fixed
Fixed
So how exactly do you recommend I approach this in my cellForRowAtIndexPath
method?
那么您究竟如何建议我在我的cellForRowAtIndexPath
方法中处理这个问题?
Thanks.
谢谢。
采纳答案by Mick MacCallum
As you stated you can't mix static and dynamic cells. However, what you can do is break up the content into different data arrays that correspond to each group. Then break the table up into difference sections and load the data from the correct array in cellForRowAtIndexPath:.
正如您所说,您不能混合静态和动态单元格。但是,您可以做的是将内容分解为与每个组对应的不同数据数组。然后将表分解为不同的部分,并从 cellForRowAtIndexPath: 中的正确数组中加载数据。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *cellID = @"CELLID";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellID forIndexPath:indexPath];
switch (indexPath.section) {
case 0:{
cell.textLabel.text = self.arrayOfStaticThings1[indexPath.row];
}break;
case 1:{
cell.textLabel.text = self.arrayOfDynamicThings[indexPath.row];
}break;
case 2:{
cell.textLabel.text = self.arrayOfStaticThings2[indexPath.row];
}break;
default:
break;
}
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
switch (section) {
case 0:{
return self.arrayOfStaticThings1.count;
}break;
case 1:{
return self.arrayOfDynamicThings.count;
}break;
case 2:{
return self.arrayOfStaticThings2.count;
}break;
default:
return 0;
break;
}
}
回答by Shan Ye
After struggled for 1 day, found best solution
经过1天的挣扎,找到了最佳解决方案
Updated for Swift 4
为 Swift 4 更新
for the case of the question:
对于问题的情况:
- Set sections of the tableView to 3
- 将 tableView 的部分设置为 3
Add a empty tableview cell in the second section which you want to apply the dynamic cells, change identifier of the cell as
WiFiTableViewCell
create a new XIB file called
WiFiTableViewCell
在要应用动态单元格的第二部分中添加一个空的 tableview 单元格,将单元格的标识符更改为
WiFiTableViewCell
创建一个名为的新 XIB 文件
WiFiTableViewCell
register the Nib in the function ViewDidLoad in tableViewController
tableView.register(UINib(nibName: "WiFiTableViewCell", bundle: nil), forCellReuseIdentifier: "WiFiTableViewCell")
add the following code to use both dynamic and static cell
override func numberOfSections(in tableView: UITableView) -> Int { return 3 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 1 { return self.dataSource.count //the datasource of the dynamic section } return super.tableView(tableView, numberOfRowsInSection: section) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if indexPath.section == 1 { let cell = tableView.dequeueReusableCell(withIdentifier: "WiFiTableViewCell") as! WiFiTableViewCell return cell } return super.tableView(tableView, cellForRowAt: indexPath) } override func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: NSIndexPath) -> Int { if indexPath.section == 1 { let newIndexPath = IndexPath(row: 0, section: indexPath.section) return super.tableView(tableView, indentationLevelForRowAt: newIndexPath) } return super.tableView(tableView, indentationLevelForRowAt: indexPath) } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath.section == 1 { return 44 } return super.tableView(tableView, heightForRowAt: indexPath) }
在 tableViewController 的函数 ViewDidLoad 中注册 Nib
tableView.register(UINib(nibName: "WiFiTableViewCell", bundle: nil), forCellReuseIdentifier: "WiFiTableViewCell")
添加以下代码以使用动态和静态单元格
override func numberOfSections(in tableView: UITableView) -> Int { return 3 } override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { if section == 1 { return self.dataSource.count //the datasource of the dynamic section } return super.tableView(tableView, numberOfRowsInSection: section) } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { if indexPath.section == 1 { let cell = tableView.dequeueReusableCell(withIdentifier: "WiFiTableViewCell") as! WiFiTableViewCell return cell } return super.tableView(tableView, cellForRowAt: indexPath) } override func tableView(_ tableView: UITableView, indentationLevelForRowAt indexPath: NSIndexPath) -> Int { if indexPath.section == 1 { let newIndexPath = IndexPath(row: 0, section: indexPath.section) return super.tableView(tableView, indentationLevelForRowAt: newIndexPath) } return super.tableView(tableView, indentationLevelForRowAt: indexPath) } override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { if indexPath.section == 1 { return 44 } return super.tableView(tableView, heightForRowAt: indexPath) }
回答by Mazen Kasser
Best and Easiest Way Yet
迄今为止最好和最简单的方法
1) Place Two Container Views in the Header and in the Footer of a Dynamic TableView 2) Assign the Static TableViews to these Containers and Untick the "Scrolling Enabled"
1) 在动态 TableView 的页眉和页脚中放置两个容器视图 2) 将静态 TableView 分配给这些容器并取消勾选“启用滚动”
Please check out my illustration at https://stackoverflow.com/a/22524085/1537178
回答by Mazen Kasser
suraj k thomas, Have a look on this structure of mine, and works perfectly. @firecast I didn't use constraints within this project, however I did set the height of the container based on the container's tableview height like so:
suraj k thomas,看看我的这个结构,效果很好。@firecast 我没有在这个项目中使用约束,但是我确实根据容器的 tableview 高度设置了容器的高度,如下所示:
ContainerViewController *containerVC = self.childViewControllers.firstObject;
CGRect frame = self.containerView.frame;
frame.origin.x = 0;
frame.origin.y = 0;
frame.size.width = self.tableView.frame.size.width;
frame.size.height = containerVC.tableView.contentSize.height;
self.containerView.frame = frame;
[self.tableView setTableHeaderView:self.containerView];
Hope this helps, let me know if you have any question.
希望这会有所帮助,如果您有任何问题,请告诉我。
回答by wajih
Add a new hidden UITableView holding your Dynamic cells
添加一个新的隐藏 UITableView 保存您的动态单元格
Steps:
脚步:
1- In your main UITableViewController
append new Section
at the end,
Inside this Section
add only one UITableViewCell
,
Insert a new UITableView
inside the Cell.
let us call the new table tblPrototypes
because
it will be the holder for the Prototype cells.
1-在你的主要UITableViewController
追加新Section
的末尾,在这个里面Section
只添加一个UITableViewCell
,UITableView
在单元格内插入一个新的。让我们称之为新表,tblPrototypes
因为它将是原型单元格的持有者。
2- Now set the type of tblPrototypes
to Dynamic Prototypes,
Then add as many prototype UITableViewCell
s as you need.
2- 现在将类型设置tblPrototypes
为动态原型,然后UITableViewCell
根据需要添加任意数量的原型。
3- Add an Outlet for tblPrototypes
in the main controller of the Main Static UITableView
,
let us call it tablePrototypes
and of course it is of type UITableView
3-tblPrototypes
在 Main Static 的主控制器中添加一个 Outlet for UITableView
,让我们调用它tablePrototypes
,当然它是类型UITableView
Coding part:
编码部分:
First make sure to hide tblPrototypes
from the UI,
Since it's the last section in your Main Table, you can do this:
首先确保tblPrototypes
从 UI 中隐藏,因为它是主表中的最后一部分,你可以这样做:
@IBOutlet weak var tblPrototypes: UITableView!
override func numberOfSections(in tableView: UITableView) -> Int {
return super.numberOfSections(in: tableView) - 1
}
The last section will not be presented.
最后一部分将不再介绍。
Now when ever you want to display a dynamic cell you do that:
现在,当您想要显示动态单元格时,您可以这样做:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let needDynamic = true
if !needDynamic {
return super.tableView(tableView, cellForRowAt: indexPath)
}
let cellId = "dynamicCellId1"
let cell = self.tblPrototypes.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
// configure the cell
return cell
}
回答by froggomad
Implement your tableView as normal using dynamic prototypes. For each custom cell, use 1 prototype. For an easy example, we'll use 2 cells, AddCell and RoomCell. AddCell is going in the first row, and RoomCell in the 2nd and any cell below.
Remember to increase your count at
numberofRowsInSection
by the appropriate number of static cells (in this case 1). So if you're returning the count of an array to determine the number of rows, it'd bereturn array.count + 1
for this example since we have 1 static cell.I usually create a custom class for each cell as well. This typically makes it simpler to configure cells in the View Controller, and is a good way to separate code, but is optional. The example below is using a custom class for each cell. If not using a custom class, replace the if let statement with an if statement without an optional cast.
使用动态原型像往常一样实现您的 tableView。对于每个自定义单元格,使用 1 个原型。举个简单的例子,我们将使用 2 个单元格,AddCell 和 RoomCell。AddCell 在第一行,RoomCell 在第二行和下面的任何单元格。
请记住
numberofRowsInSection
通过适当数量的静态单元格(在本例中为 1)来增加计数。因此,如果您要返回数组的计数来确定行数,则return array.count + 1
适用于本示例,因为我们有 1 个静态单元格。我通常也会为每个单元格创建一个自定义类。这通常会使在 View Controller 中配置单元格变得更简单,并且是分离代码的好方法,但它是可选的。下面的示例为每个单元格使用自定义类。如果不使用自定义类,请将 if let 语句替换为不带可选强制转换的 if 语句。
note: configureCell
below is a method in the custom class RoomCell
that dynamically configures the cell
注意:configureCell
下面是RoomCell
动态配置单元格的自定义类中的一个方法
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: "AddCell", for: indexPath) as? AddCell {
return cell
}
} else {
if let cell = tableView.dequeueReusableCell(withIdentifier: "RoomCell", for: indexPath) as? RoomCell {
cell.configureCell(user: user, room: room)
return cell
}
}
return UITableViewCell() //returns empty cell if something fails
}