1

我创建了一个UITableView包含自定义部分标题视图。现在,我希望它在最上面的当前可见部分显示更多数据。我计划使用该事件scrollViewDidEndDecelerating来更新节标题。目前,问题是我无法为特定节号设置节标题高度。

我确实尝试过使用heightForHeaderInSection,但应用程序只是崩溃并显示以下输出:

'NSRangeException', reason: '*** -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'

我正在使用代码:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    if (tableView == self.tableView)
    {
        NSArray *visibleCells = [self.tableView visibleCells];
        NSMutableArray *visibleSections = [[NSMutableArray alloc] init];
        for (NSInteger index = 0; index < [visibleCells count]; index++)
        {
            UITableViewCell *currentCell = [visibleCells objectAtIndex:index];
            NSIndexPath *currentPath = (NSIndexPath *)[self.tableView indexPathForCell:currentCell];
            if (![visibleSections containsObject:[NSNumber numberWithInt:currentPath.section]])
            {
                [visibleSections addObject:[NSNumber numberWithInt:currentPath.section]];
                NSLog([NSString stringWithFormat:@"%ld", (long)[visibleSections count]]);
                [visibleSections sortedArrayUsingDescriptors:[NSArray arrayWithObject:[[NSSortDescriptor alloc] initWithKey:nil ascending:YES]]];
            }
        }
        if (visibleSections == nil)
        {
            return 42.0;
        }
        else if ([[visibleSections objectAtIndex:0] integerValue] == section)
        {
            return 58.0;
        }
        else
        {
            return 42.0;
        }
    }
}

我无法完全弄清楚我的heightForHeaderInSection方法出了什么问题,但我知道它与NSMutableArray, visibleSections 有关。

关于如何更改外部特定部分标题视图的高度heightForHeaderInSection和/或如何修复上面的代码的任何提示或答案将非常有帮助。

编辑:

只是为了让我的崩溃问题的解决方案更清楚一点,if (visibleSections == nil)不应该用来代替if ([visibleSections count] < 1)or if ([visibleSections count] == 0)

4

4 回答 4

1

我认为您也可以这样做,如果您希望在表格首次出现时第一节标题更高(topSection 是一个 NSInteger 属性):

-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    self.topSection = ((NSIndexPath *)[self.tableView indexPathsForVisibleRows][0]).section;
    [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:self.topSection] withRowAnimation:NO];
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {

        if (self.topSection == section)
        {
            return 58.0;
        }
        else
        {
            return 42.0;
        }
}
于 2013-04-06T18:08:15.383 回答
0

您不能通过调用 objectAtIndex:0 直接引用数组第一个对象,您必须保持防御,因此请更改此:

else if ([[visibleSections objectAtIndex:0] integerValue] == section)
    {
        return 58.0;
    }

else if([visibleSections count]>0)
    {
      if ([[visibleSections objectAtIndex:0] integerValue] == section)
        {
           return 58.0;
        }
     }
于 2013-04-06T17:04:49.337 回答
0

好的,事实证明这是一个比最初看起来更难的问题。到目前为止我想出的最好的是

  • 不要对顶部的标题进行任何不同的处理,并用额外的数据填充它们。
  • 您可以通过巧妙地定位“附加”项目来显示和隐藏不同的部分,以便它们在父视图较小时超出父视图的边界并制作父视图clipToBounds
  • 如果您无法创建自定义UIView子类并在layoutSubviews

我决定的最终实现是这样的

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
  NSArray *indexPaths = [self.tableView indexPathsForVisibleRows];
  self.topSection = [indexPaths count] ? [indexPaths[0] section] : -1;
  if (indexPaths.count > 1) {
    self.topSection = [indexPaths[1] section];
  }

  [self.tableView beginUpdates];
  [self.tableView endUpdates];
}

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section;
{
  if (section <= self.topSection) {
    return 60;
  } else {
    return 20;
  }
}

它绝不是完美的,但它看起来是半合理的,可以调整。

注意事项:

  • 您可能需要评估是否有太多的工作正在进行,scrollViewDidScroll:但它似乎并没有对我造成任何滞后(我没有真正正确地测试过)
  • 如果可用,我使用第二个设置顶部,indexPath因为它看起来更令人愉悦/不那么笨重
  • 我之所以使用section <= self.topSection,是因为标题的前面都是屏幕,所以没有必要减小它们的大小,这会导致动画非常笨拙。

因此,在尝试此操作后,您可能需要更深入地挖掘或想要重新考虑您的设计

于 2013-04-06T21:37:24.760 回答
-1

尝试更改此行:

NSMutableArray *visibleSections = [[NSMutableArray alloc] init]

到:

NSMutableArray *visibleSections = [NSMutableArray array];

初始化数组。

于 2013-04-06T17:02:01.710 回答