UITableView点击以取消选择单元格

时间:2012-10-02 15:28:28

标签: iphone ios uitableview

点击时我选择了UITableViewCell。在此选定状态期间,如果用户再次点击该单元格,我希望该单元格取消选择。

我找不到任何被调用的委托调用。任何想法如何实现这一点?它真的会成为手势识别器吗?

14 个答案:

答案 0 :(得分:33)

您实际上可以使用委托方法willSelectRowAtIndexPath:

执行此操作
- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if ([cell isSelected]) {
        // Deselect manually.
        [tableView.delegate tableView:tableView willDeselectRowAtIndexPath:indexPath];
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        [tableView.delegate tableView:tableView didDeselectRowAtIndexPath:indexPath];

        return nil;
    }

    return indexPath;
}

请注意deselectRowAtIndexPath:不会自动调用委托方法,因此您需要手动调用这些调用。

答案 1 :(得分:16)

在Swift 4中:

func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {

    if let indexPathForSelectedRow = tableView.indexPathForSelectedRow,
        indexPathForSelectedRow == indexPath {
        tableView.deselectRow(at: indexPath, animated: false)
        return nil
    }
    return indexPath
}

答案 2 :(得分:4)

这是一个更清洁的解决方案:

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    if ([[tableView indexPathForSelectedRow] isEqual:indexPath]) {
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        return nil;
    }
    return indexPath;
}

答案 3 :(得分:3)

我认为使用蓝色选择着色进行切换可能会给人一种奇怪的印象。为什么不使用像复选标记这样的配件?这是一种更为熟悉的选择切换技术(无论是多单元还是单单元)。

有关信息,请参阅此答案: UITableView Multiple Selection

答案 4 :(得分:3)

- (NSIndexPath *)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
    if ([cell isSelected]) {
        // Deselect manually.
        if ([tableView.delegate respondsToSelector:@selector(tableView:willDeselectRowAtIndexPath:)]) {
            [tableView.delegate tableView:tableView willDeselectRowAtIndexPath:indexPath];
        }
        [tableView deselectRowAtIndexPath:indexPath animated:YES];
        if ([tableView.delegate respondsToSelector:@selector(tableView:didDeselectRowAtIndexPath:)]) {
            [tableView.delegate tableView:tableView didDeselectRowAtIndexPath:indexPath];
        }
        return nil;
    }

    return indexPath;
}

答案 5 :(得分:3)

使用“多选”模式时,单击已选择的行时,将不会调用“didSelectRowAtIndexPath”。在“单选”模式下仍可以编程方式选择多行,并且所有点击的行都会触发didSelectRowAtIndexPath。

只是遇到遇到同样问题的人。

答案 6 :(得分:2)

选择单元格时,将触发此委托方法。

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


        UITableViewCell *theUITableViewCell = [tableView cellForRowAtIndexPath:path];
        if (theUITableViewCell.selected == YES){
            self.tableView deselectRowAtIndexPath:<#(NSIndexPath *)#> animated:<#(BOOL)#>
            // Do more thing
        }else{
            // By default, it is highlighted for selected state
        }

 }

这是伪代码。

答案 7 :(得分:2)

你可以尝试这个,它适用于我(单选或多选):

一个。在viewDidLoad中分配一个私有NSMutableArray,如:

@interface XXXViewController : UIViewController <UITableViewDataSource, UITableViewDelegate>
{
    NSMutableArray * selectedZoneCellIndexPaths;
}


- (void)viewDidLoad
{
    selectedZoneCellIndexPaths = [[NSMutableArray alloc] init];
}

B中。在UITableViewDelegate didSelectRow中添加以下行

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

     for (NSIndexPath * iter in selectedZoneCellIndexPaths)
     {
         if (indexPath.section == iter.section && indexPath.row == iter.row)
         {
             [tableView deselectRowAtIndexPath:indexPath animated:YES];
             [selectedZoneCellIndexPaths removeObject:iter];
             return;
         }
     }
     [selectedZoneCellIndexPaths addObject:indexPath];
     return;
}

答案 8 :(得分:1)

斯威夫特的狡猾版本答案:

public func tableView(tableView: UITableView, willSelectRowAtIndexPath indexPath: NSIndexPath) -> NSIndexPath? {
  let cell = tableView.cellForRowAtIndexPath(indexPath)
  if (cell?.selected ?? false) {
    // Deselect manually.
    tableView.delegate!.tableView?(tableView, willDeselectRowAtIndexPath: indexPath)
    tableView.deselectRowAtIndexPath(indexPath, animated: true)
    tableView.delegate!.tableView?(tableView, didDeselectRowAtIndexPath: indexPath)
    return nil
  }
return indexPath;
}

答案 9 :(得分:1)

来自@prisonerjohn,以防有人想知道如何检查委托是否像@Patrick所说的那样响应选择器,在 Swift 3

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    print(indexPath)
    if colorCelllExpandedIndex != nil{
        colorCelllExpandedIndex = nil
    } else {
        colorCelllExpandedIndex = indexPath
    }
    tableView.beginUpdates()
    tableView.endUpdates()

}

override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
    if indexPath == colorCelllExpandedIndex {
        return CGFloat(colorCellExpandedHeight)
    } else {
        if indexPath.row == 0 {
            return CGFloat(colorCellRegularHeight)
        }
        return UITableViewAutomaticDimension
    }
}

答案 10 :(得分:1)

迅速5。

UITableViewDelegate中,它很简单,如下所示:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    tableView.deselectRow(at: indexPath, animated: true)
}

答案 11 :(得分:0)

我是在追求同样的事情,但@occulus'answer为我提供了我所缺少的暗示。

这让我意识到完成这项工作的方法是允许在表视图中进行多项选择,并在使用其中一种委托方法选择新行时手动取消选择以前选择的行。

在单选模式下,表视图尝试尽可能多地选择一行,因此在点击所选行时不会取消选择,这似乎很自然。

答案 12 :(得分:0)

保持单一选择模式不变,但覆盖以下类似功能:

override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath? {
    if tableView.indexPathsForSelectedRows?.contains(indexPath) ?? false {
       tableView.deselectRow(at: indexPath, animated: true)
       return nil
    }

    return indexPath
}

override func tableView(_ tableView: UITableView, willDeselectRowAt indexPath: IndexPath) -> IndexPath? {
    return nil
}

答案 13 :(得分:-4)

也许我的问题不够具体,但这两个答案对我所追求的有点宽泛。

似乎这是不可能的,我使用单元格的手势识别器手动设置选定/未选择状态。