uitableview:嵌套节标题

发布于 2024-12-08 15:41:18 字数 608 浏览 0 评论 0原文

我正在尝试实现具有以下结构的 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

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

我如何实现这个?或者已经有人实施过这个了吗?

谢谢 :)

Im trying to implement a uitableview with the following structure:

  • section group 0
    • section 0
      • cell 0
      • cell 1
      • cell 2
    • section 1
      • cell 0
      • cell 1
      • cell 2
  • section group 1
    • section 0
      • cell 0
      • cell 1
      • cell 2
    • section 1
      • cell 0
      • cell 1
      • cell 2

and it should scoll like this screenshot (1-2-3-4):
http://dl.dropbox.com/u/2213241/uitableview.png

So always two sections are visible.

How do i implement this? Or has anyone implemented this already?

Thanks :)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜未央樱花落 2024-12-15 15:41:18

拥有嵌套部分的技巧是在表视图中拥有两种类型的行。一个代表第二级部分,另一个代表表视图中的普通行。假设您有一个两级数组(例如部分)来表示表视图中的项目。

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

- (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];
}

这里有一篇详细的文章介绍如何执行此操作。

The trick to have nested sections is to have two kinds of rows in the table view. One to represent the second level of sections and another to represent the normal rows in the tableview. Let's say you have a two level array (say sections) to represent the items in your table view.

Then, the total number of sections that we have are just the number of top level sections. The number of rows in each top level section would be the number of subsections + the number of rows in each subsection.

- (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;
}

Now, all we need to think about is how to create the rows for the table view. Set up two prototypes in the storyboard with different reuse identifiers, one for the section header and another for row item and just instantiate the correct one based on the asked index in the data source method.

- (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 on how to do this.

烟雨凡馨 2024-12-15 15:41:18

如果有人对上述代码的 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)
}

In case anyone is interested in a Swift 4.2 version of the above code here it is.

In order to have nested sections, you need to have several kinds of rows in your tableView. First to represent the second level of sections and second to represent the standard rows in your tableView. Let's say you have a two-level array (sections) to represent the items in your tableView.

Then, the total number of sections that we have are just the number of top-level sections. The number of rows in each top-level section would be the number of subsections + the number of rows in each subsection.

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
}

Now, all you need to think about is how to create the rows for the tableView. Set up two prototypes in the storyboard with different reuse identifiers, one for the section header and another for row item and just instantiate the correct one based on the asked index in the data source method.

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)
}
猫瑾少女 2024-12-15 15:41:18

子类化 UITableView 将是一个不错的选择,就像 Robin 建议的那样。我自己也做过类似的事情,但我对 UITableViewCell 进行了子类化,并将 UITableView 放置在其中。在这种情况下,您将有一个基本 tableView,其中每个部分都是一个组。由于您对 UITableViewCell 进行了子类化,所以每一行都是它自己的 UITableView,它有自己的部分和行。这应该会给您带来您正在寻找的外观和功能。如果您在安装时遇到困难,我很乐意帮助您进行设置,但这并不难。 本教程给出了如何子类化 UITableViewCell 的一个很好的示例 是一个很好的起点

Subclassing UITableView would be a good option, like robin suggested. I've done something similar to this myself, but I subclassed UITableViewCell and placed UITableViews inside them. In this case, you would have a base tableView where each section would be a group. Each row, because you subclass UITableViewCell, is then its own UITableView, which has its own sections and rows. This should give you the look and functionality you are looking for. I'd be happy to help set it up if you have trouble getting it in place, but it's not too hard to do. This tutorial gives a good example how to subclass UITableViewCell and is a good place to start

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文