在iOS中展开和折叠表视图单元格

20

我有一个自定义单元格的表视图和每个单元格中的一些按钮。单击单元格内的任何按钮将在该单元格下方显示另一个自定义视图。再次单击相同的按钮将折叠视图,并需要对所有单元格执行相同的操作。我尝试在按钮点击时使用insertrow方法,但失败了。如何仅使用表视图委托来实现这一点。

这是我尝试过的内容:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *simpleTableIdentifier = @"CustomCell_For_Dashboard";

    CustomCellFor_Dashboard  *customCell = (CustomCellFor_Dashboard *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
    if (customCell == nil)
    {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCellFor_Dashboard" owner:self options:nil];
        customCell = [nib objectAtIndex:0];
    }
    [customCell.howyoulfeelBtn  addTarget:self action:@selector(buttonclicked:) forControlEvents:UIControlEventTouchUpInside];
      customCell.nameLabel.text = @"test";
    customCell.imgView.image = [UIImage imageNamed:@"Default.png"];
   // customCell.prepTimeLabel.text = [prepTime objectAtIndex:indexPath.row];
    return customCell;
}

-(void)buttonclicked:(id)sender{
    NSIndexPath *indexPath = [myTable indexPathForCell:sender];


    [myTable beginUpdates];

     NSIndexPath *insertPath = [NSIndexPath indexPathForRow:indexPath.row inSection:indexPath.section];
   [myTable insertRowsAtIndexPaths:[NSArray arrayWithObject:insertPath] withRowAnimation:UITableViewRowAnimationTop];
  } 

有人可以帮助我吗?


对于Swift,请查看此链接http://www.iostutorialjunction.com/2017/03/expandable-and-collapsable-uitableview-using-Swift3.html。 - Aman Aggarwal
4个回答

33

我在一个项目中得到了同样的任务,只有一点不同:没有按钮,只需点击单元格即可展开或折叠它。

您需要在代码中编辑几个地方。首先,按钮方法的代码将类似于以下内容:

- (void) collapseExpandButtonTap:(id) sender
{
    UIButton* aButton = (UIButton*)sender; //It's actually a button
    NSIndexPath* aPath = [self getIndexPathForCellWithButtonByMagic:aButton];
    //expandedCells is a mutable set declared in your interface section or private class extensiont
    if ([expandedCells containsObject:aPath])
    {
        [expandedCells removeObject:aPath];
    }
    else
    {
        [expandedCells addObject:aPath];
    }
    [myTableView beginEditing];
    [myTableView endEditing]; //Yeah, that old trick to animate cell expand/collapse
}

现在第二件事是 UITableViewDelegate 方法:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([expandedCells containsObject:indexPath])
    {
        return kExpandedCellHeight; //It's not necessary a constant, though
    }
    else
    {
        return kNormalCellHeigh; //Again not necessary a constant
    }
}

重要的是要确定您的单元格是应该展开/折叠并在委托方法中返回正确的高度。


6
在Storyboard中确保将表格单元设置为“剪裁子视图”,否则您想隐藏的内容将会显示出来。 - Kalel Wade
感谢 @KalelWade 的提示。 - rweavere
Swift3解决方案,http://www.iostutorialjunction.com/2017/03/expandable-and-collapsable-uitableview-using-Swift3.html - Aman Aggarwal
2
@eagle.dan.1349,NSIndexPath* aPath = [self indexPathForCellWithButtonTag:aButton.tag] 出现错误。'ViewController' 没有声明 'indexPathForCellWithButtonTag:' 选择器的可见接口。 你能帮我吗? - Neeraj Joshi
@Nij,这种方法的实现细节取决于读者是否愿意超越仅仅从SO中复制粘贴 :P - eagle.dan.1349

17

根据 @eagle.dan.1349 的说法,以下是如何在单元格点击时进行操作。在Storyboard中,您还需要将表格单元设置为剪切子视图,否则隐藏的内容将会显示出来。

.h

@property (strong, nonatomic) NSMutableArray *expandedCells;

.m

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{

    if ([self.expandedCells containsObject:indexPath])
    {
        [self.expandedCells removeObject:indexPath];
    }
    else
    {
        [self.expandedCells addObject:indexPath];
    }
    [tableView beginUpdates];
    [tableView endUpdates];
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    CGFloat kExpandedCellHeight = 150;
    CGFloat kNormalCellHeigh = 50;

    if ([self.expandedCells containsObject:indexPath])
    {
        return kExpandedCellHeight; //It's not necessary a constant, though
    }
    else
    {
        return kNormalCellHeigh; //Again not necessary a constant
    }
}

10

看到这篇文章,我想提供我的建议,因为我的解决方案与选定的答案非常相似(整个区域的轻敲)。

许多人仅使用单元格进行架构设计,但我认为有一种方法可以构建这个功能来更好地满足人们的需求:

标题单元格标题应该是可点击的,然后在标题下方的单元格显示或隐藏。这可以通过向标题添加手势识别器来实现,当轻触时,您只需删除该标题下面的所有单元格(该部分),反之亦然(添加单元格)。当然,您必须维护“打开”和“关闭”的哪些标题的状态。

这个方案有几个优点:

  1. 标题和单元格的工作是分离的,使代码更加清晰。
  2. 此方法与表视图的构建方式(标题和单元格)非常匹配,因此没有太多的魔法 - 代码只是删除或添加单元格,并且应与后续版本的iOS兼容。

我制作了一个非常简单的库来实现这一点。只要您的表视图设置为UITableView部分标题和单元格,您需要做的就是子类化表视图和标题。

链接:https://github.com/fuzz-productions/FZAccordionTableView

图片描述


0

我也遇到了同样的情况,我的解决方案是在章节标题上放置一个按钮,并使用viewForHeaderInSection方法。

noOfRows定义每个章节中有多少行,button.tag记录哪个章节的按钮被按下。

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
    UIButton *btnSection = [[UIButton alloc] initWithFrame:CGRectMake(0, 0, tableView.frame.size.width, tableView.frame.size.height)];
    btnSection.tag = section;   
    [btnSection setTitle:[sectionArray objectAtIndex:section] forState:UIControlStateNormal];
    [btnSection addTarget:self action:@selector(sectionButtonTapped:) forControlEvents:UIControlEventTouchUpInside];

    return btnSection;
} 

- (void)sectionButtonTapped:(UIButton *)button {
    sectionIndex = button.tag;
    if (button.tag == 0) {
        noOfRows = 3;
    } else if (button.tag == 1) {
        noOfRows = 1;
    } else if (button.tag == 2) {
        noOfRows = 2;
    }

    [self.tableView reloadData];
}

希望这能对你有所帮助。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接