【问题标题】:showing and hiding a specific cell type in a UITableView (possibly with animation)在 UITableView 中显示和隐藏特定的单元格类型(可能带有动画)
【发布时间】:2014-10-29 20:23:36
【问题描述】:

我有一个 UITableView 并且已经看到了这种效果,并希望为我们的以下数据实现它:

menu_header
  menu_subheader
    * item
    * item
  menu_subheader
    * item
    * item  
    * item

基本上,我只想显示标题和子标题,然后当用户单击其中一个子标题时,它会显示项目(最好在动画块中)并适当地向下或向上调整其他单元格。像这样:

是否有一个预先构建的组件可以做到这一点?想一想,似乎我想将这些项目单元格设置为隐藏。我见过这个https://github.com/peterpaulis/StaticDataTableViewController,但它看起来不适用于动态数据。看起来这应该很简单。关于如何完成这项工作的任何想法?理想情况下,我希望它能够在您单击它时插入数据,然后如果您单击另一个子标题,请关闭另一个子标题并添加到该子标题。

【问题讨论】:

  • 我以前做过类似的事情,但我不确定你所说的“副标题”是什么意思。通常有部分,部分有标题/视图,然后部分中有单元格。它实际上只是二维信息。当您谈论标题和子标题以及单元格时,听起来您的意思是 3 维?
  • 基本上,它是一个树结构,因此可以有多个级别的子标题(基本上来自 Rails 的acts_as_tree 数据结构)。当我说headers 时,我并不是在考虑 UITableView 标头,但不幸的是,这就是我们所说的。目前,我将这个数据结构展平并呈现所有项目,并且可以是headeritem。所以我想做的是有一个只显示标题的表格视图,然后,一旦你点击,它就会显示该标题的项目。

标签: ios uitableview ios7


【解决方案1】:

您必须在表格视图中删除和插入单元格,而不是修改它们的高度。

我们将controller 用于表格视图,让您在实际处理表格视图中行的删除/重新插入时“隐藏/显示”单元格。

“切换详细信息”在 Demo 上的工作方式与您想要实现的非常相似:

- (IBAction)toggleDetails:(id)sender
{
    // Hide if all hiddeable rows are hidden, show all otherwise
    [self.topSection setObjectsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(1, 3)]
                                  hidden:(![self.topSection isObjectAtIndexHidden:1] &&
                                          ![self.topSection isObjectAtIndexHidden:2] &&
                                          ![self.topSection isObjectAtIndexHidden:3])];
}

更改单元格的高度以“隐藏”它们并不是最佳选择,因为代理将被多次询问其大小,并且单元格仍将被实例化和配置但不可见。


示例库在重用单元格时将行数据保存在内存中(每行一个对象)。这对于大多数项目来说应该没问题,但也许在你的情况下,不仅所有对象都不应该在内存上,而且你也不应该一次获取所有对象。

【讨论】:

  • 嗯...为什么你认为操纵高度是在破解它?最初,我打算进行插入/删除,但操作高度似乎更干净......我们将有一些大表(几千行)所以当我开始实施时,我会很好奇看看哪种方法效果更好.
  • “几千”行?那时高度可能不是要走的路,但我也建议单张桌子也不对,折叠或不折叠。很难与之进行有意义的互动。
  • 我会说 2000 年将是高端。对于我们的第一个客户,我们有一个大约 500 个,并且认为可能更大。性能很好 - 加载带有表格视图的 ViewController 可能有 1-2 秒的延迟。由于它模仿了真实世界的文档(大约 20 页),因此我无法将其拆分。但是 500 项列表是创建更可导航结构的动机的一部分。我会更多地研究你的例子,非常感谢你的反馈。
【解决方案2】:

我其实只是想添加评论,但声誉问题...

无论如何,我个人最喜欢的扩展/折叠 UITableView 部分的方式在这篇文章中有所描述:https://stackoverflow.com/a/1941766/2440562

如果我正确理解问题,menu_headersmenu_subheaders 将始终可见,并且只有项目会显示/隐藏。

所以这是我的想法(让我们看看我是否能解释得足够好): 您可能知道每个 menu_header 将拥有多少个 menu_subheaders(静态计数或数组元素的数量),因此您可以为每个 menu_header 添加一个部分(实际上只包含一行或标题) 以及在它们之间您可以添加可扩展部分 (menu_subheaders),可以如我上面提到的答案所示进行管理。当您想在点击另一个时折叠先前展开的menu_subheader,您可以重置其布尔值并使用reloadSections 方法重新加载两者。您必须计算menu_headersmenu_subheaders 的位置,但基本上您不必处理单元格高度和行插入和删除(这实际上是我最喜欢的部分)。

这是我提到的计算的快速代码 sn-p(未经测试,完全即兴创作):

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return <number_of_menu_headers> + <number_of_menu_subheaders>;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0) {
        // handle first menu_header
    } else if (indexPath.section < 1 + <number_of_menu_subheaders1>) {
        if (indexPath.row == 0) {
            // handle the menu_subheader header row
        } else {
            // handle the rest of the items
        }       
    } else if (indexPath.section == 1 + <number_of_menu_subheaders1>) {
        // handle second menu_header
    } else if (indexPath.section < 2 + <number_of_menu_subheaders1> + <number_of_menu_subheaders2>) {
        if (indexPath.row == 0) {
            // handle the menu_subheader header row for the current menu_subheader
        } else {
            // handle the rest of the items for the current menu_subheader
        }       
    } etc...
}

再次,只是一个想法......

【讨论】:

    【解决方案3】:

    要在表格视图中实现“折叠”,您有两种选择:

    • 根据每个部分的折叠/展开属性控制部分中的单元格数量。折叠或展开时,使用 tableView 上的insertdeleteRowsAtIndexPaths:withRowAnimation: 方法。
    • 使用委托方法控制单元格的高度。根据每个部分的折叠/展开属性为折叠部分返回零。折叠或展开时,调用beginUpdates,然后立即调用endUpdates 以重新计算高度并为新布局设置动画。

    我在this GitHub repo 中创建了第二个选项的简单实现。如果您对此还有其他问题,请告诉我。

    【讨论】:

    • 你的第二个策略听起来像我在概念上试图做的,但嗯....实际上是另一个故事。你有一些示例代码的链接吗?我用谷歌搜索了几个小时,得到了一些非常不稳定的结果。作为第一次迭代,我希望只有一个 section 可见,但老实说,每个 menu_header 的 toggle 按钮将是理想的
    • 您的问题是隐藏和显示行,还是控制隐藏/显示?
    • 谢谢,这真的很有帮助。我正在尝试整合我们今天的一些数据。因为,menuHeaders 可以有多个级别(类似于 Rails 的acts_as_tree),使用部分会出现问题,因为它不支持子部分。想像用[rowInTable isKindOfClass:[CTVMenuHeader class]] 签入cellForRowAtIndexPath 之类的事情。今天晚些时候我会试着让一些东西工作
    • 所以我刚刚更新了 github 存储库,并认为它几乎在那里......丑)但越来越近了
    • @rivera 这不是最佳的,不,但根据显示的数据量,它通常会更简单 很多,在性能或内存使用方面没有明显差异。请注意,我的第一个建议添加和删除单元格。
    【解决方案4】:

    有一个sample code from Apple 可以帮助您获得此结果。
    主要区别在于 Apple 示例代码中的标题是触发操作并显示相关子视图的标题,但这不是阻塞问题。
    您可以使用普通单元格来实现这一点,方法是在选择其中一个行时插入和删除行。
    重要的是您需要重新映射数据源信息或将信息与另一个集合配对以获取该单元格的状态:打开或关闭以及子标题或项目以识别它们并在选择它时选择正确的操作。
    同样重要的是保持数据模型(数据源)和单元格数量之间的一致性,如果您使用批处理操作来插入和删除单元格,则不会有问题。如果你不这样做,你会看到很多例外。
    也可以看看here

    【讨论】:

      【解决方案5】:

      将您的标题设为 Tableview Section,子标题设为 Row... 在 didSelectRow 委托方法中插入行,这将是您的项目。

      【讨论】:

      • 嗯...有趣的策略 - 你做过这个吗?
      • 是的......我正在研究这个。在我的情况下,我需要在每次点击时扩展和缩小单元格......
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-12-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多