【问题标题】:uitableview: nested section headersuitableview:嵌套的节标题
【发布时间】:2011-10-04 15:23:20
【问题描述】:

我正在尝试使用以下结构实现 uitableview:

  • 节组 0
    • 第 0 节
      • 单元格 0
      • 单元格 1
      • 单元格 2
    • 第 1 节
      • 单元格 0
      • 单元格 1
      • 单元格 2
  • 节组 1
    • 第 0 节
      • 单元格 0
      • 单元格 1
      • 单元格 2
    • 第 1 节
      • 单元格 0
      • 单元格 1
      • 单元格 2

它应该像这个屏幕截图 (1-2-3-4) 一样: http://dl.dropbox.com/u/2213241/uitableview.png

所以总是有两个部分是可见的。

我该如何实现呢?或者有人已经实现了吗?

谢谢:)

【问题讨论】:

  • 那么我的问题是你想实现这样的东西吗?
  • 是的,我试图实现这一点,但无法弄清楚如何实现。所以我认为比我聪明的人有一个想法;)
  • 实现起来并不难,但也不简单,也许你可以从继承 uitable view 开始,然后发布一些相关的问题

标签: ios iphone uitableview header


【解决方案1】:

嵌套部分的诀窍是在表格视图中有两种类型的行。一个代表第二级部分,另一个代表表格视图中的正常行。假设您有一个两级数组(例如部分)来表示表格视图中的项目。

那么,我们拥有的部分的总数就是顶级部分的数量。每个顶级部分的行数将是子部分的数量 + 每个子部分的行数。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return self.sections.count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    NSArray *sectionItems = self.sections[(NSUInteger) section];
    NSUInteger numberOfRows = sectionItems.count; // For second level section headers
    for (NSArray *rowItems  in sectionItems) {
        numberOfRows += rowItems.count; // For actual table rows
    }
    return numberOfRows;
}

现在,我们需要考虑的是如何为表格视图创建行。在情节提要中设置两个具有不同重用标识符的原型,一个用于节标题,另一个用于行项,然后根据数据源方法中的询问索引实例化正确的一个。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    NSMutableArray *sectionItems = self.sections[(NSUInteger) indexPath.section];
    NSMutableArray *sectionHeaders = self.sectionHeaders[(NSUInteger) indexPath.section];
    NSIndexPath *itemAndSubsectionIndex = [self computeItemAndSubsectionIndexForIndexPath:indexPath];
    NSUInteger subsectionIndex = (NSUInteger) itemAndSubsectionIndex.section;
    NSInteger itemIndex = itemAndSubsectionIndex.row;

    if (itemIndex < 0) {
        // Section header
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"SECTION_HEADER_CELL" forIndexPath:indexPath];
        cell.textLabel.text = sectionHeaders[subsectionIndex];
        return cell;
    } else {
        // Row Item
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"ROW_CONTENT_CELL" forIndexPath:indexPath];
        cell.textLabel.text = sectionItems[subsectionIndex][itemIndex];
        return cell;
    }
}

- (NSIndexPath *)computeItemAndSubsectionIndexForIndexPath:(NSIndexPath *)indexPath {
    NSMutableArray *sectionItems = self.sections[(NSUInteger) indexPath.section];
    NSInteger itemIndex = indexPath.row;
    NSUInteger subsectionIndex = 0;
    for (NSUInteger i = 0; i < sectionItems.count; ++i) {
        // First row for each section item is header
        --itemIndex;
        // Check if the item index is within this subsection's items
        NSArray *subsectionItems = sectionItems[i];
        if (itemIndex < (NSInteger) subsectionItems.count) {
            subsectionIndex = i;
            break;
        } else {
            itemIndex -= subsectionItems.count;
        }
    }
    return [NSIndexPath indexPathForRow:itemIndex inSection:subsectionIndex];
}

Here's a detailed post 了解如何执行此操作。

【讨论】:

【解决方案2】:

如果有人对上述代码的 Swift 4.2 版本感兴趣,这里就是。

为了有嵌套的部分,你需要在你的 tableView 中有几种类型的行。第一个表示第二级部分,第二个表示 tableView 中的标准行。假设您有一个两级数组(部分)来表示 tableView 中的项目。

那么,我们拥有的部分的总数就是顶级部分的数量。每个顶级节中的行数将是子节数 + 每个子节中的行数。

func numberOfSections(in tableView: UITableView) -> Int {
    return sections.count
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    let sectionItems = sections[section]
    var numberOfRows: Int = sectionItems.count // For second level section headers
    for rowItems: [Any] in sectionItems as? [[Any]] ?? [] {
        numberOfRows += rowItems.count // For actual table rows
    }
    return numberOfRows
}

现在,您需要考虑的是如何为 tableView 创建行。在情节提要中设置两个具有不同重用标识符的原型,一个用于节标题,另一个用于行项,然后根据数据源方法中的询问索引实例化正确的一个。

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var sectionItems = sections[indexPath.section]
    var sectionHeaders = self.sectionHeaders[indexPath.section]
    let itemAndSubsectionIndex: IndexPath? = computeItemAndSubsectionIndex(for: indexPath)
    let subsectionIndex = Int(itemAndSubsectionIndex?.section ?? 0)
    let itemIndex: Int? = itemAndSubsectionIndex?.row

    if (itemIndex ?? 0) < 0 {
        // Section header
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "SECTION_HEADER_CELL", for: indexPath)
        cell.textLabel?.text = sectionHeaders[subsectionIndex] as? String
        return cell
    } else {
        // Row Item
        let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "ROW_CONTENT_CELL", for: indexPath)
        cell.textLabel?.text = sectionItems[subsectionIndex][itemIndex ?? 0] as? String
        return cell
    }
}

func computeItemAndSubsectionIndex(for indexPath: IndexPath?) -> IndexPath? {
    var sectionItems = sections[Int(indexPath?.section ?? 0)]
    var itemIndex: Int? = indexPath?.row
    var subsectionIndex: Int = 0
    for i in 0..<sectionItems.count {
        // First row for each section item is header
        itemIndex = (itemIndex ?? 0) - 1
        // Check if the item index is within this subsection's items
        let subsectionItems = sectionItems[i] as? [Any]
        if (itemIndex ?? 0) < Int(subsectionItems?.count ?? 0) {
            subsectionIndex = i
            break
        } else {
            itemIndex -= subsectionItems?.count
        }
    }
    return IndexPath(row: itemIndex ?? 0, section: subsectionIndex)
}

【讨论】:

  • 变量是如何声明的??你能举个例子吗?
【解决方案3】:

子类化UITableView 将是一个不错的选择,就像 robin 建议的那样。我自己也做过类似的事情,但我将UITableViewCell 子类化并将UITableViews 放入其中。在这种情况下,您将拥有一个基本 tableView,其中每个部分都是一个组。由于您将UITableViewCell 子类化,因此每一行都是它自己的UITableView,它有自己的部分和行。这应该为您提供您正在寻找的外观和功能。如果您无法将其安装到位,我很乐意帮助您进行设置,但这并不难。 This tutorial 给出了一个很好的例子,如何继承 UITableViewCell 并且是一个很好的起点

【讨论】:

  • 是的,应该可以的。如果您不想使用 IB,也可以通过编程方式完成。只需在头文件中设置 tableView 和其他变量,然后在自定义单元格的 initWithStyle:reuseIdentifier: 方法中创建 tableView。其余代码将是相同的,但如果您不想为自定义单元格创建 nib 文件,则可以这样做
  • 这是 imo 有趣和有创意的东西。感谢分享
猜你喜欢
  • 1970-01-01
  • 2022-11-18
  • 1970-01-01
  • 2012-03-22
  • 2012-01-04
  • 1970-01-01
  • 2018-10-14
  • 1970-01-01
  • 2010-11-15
相关资源
最近更新 更多