【问题标题】:UITableViewCell Accessory Type Checked on Tap & Set other uncheckedUITableViewCell 附件类型在点击时选中并设置其他未选中
【发布时间】:2010-12-17 13:40:48
【问题描述】:

我对设置表格视图单元配件有点困惑。

我在我的表格中修复了两个部分

  • 首页
  • 办公室

我想要的是如下......

  • 当用户点击任何单元格时
  • 单元格被选中 &
    • 我想设置为已选中(设置 uitableviewcell 附件类型 - 已选中单元格)
  • 现在所有其他单元格的附件类型也应设置为
    • 适用的视图单元配件类型无

我尝试了以下代码。但我发现 indexpath.row & indexpath.section 是只读属性。

// Override to support row selection in the table view.
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {    
    [tblProfileView deselectRowAtIndexPath:indexPath animated:YES];
    int i,max;
    UITableViewCell *x; NSIndexPath *tt;

    for(i=0;i<[tblProfileView numberOfRowsInSection:0];i++)
    {
        tt.row=i; tt.section=0;
        x=[tblProfileView cellForRowAtIndexPath:];
        [x setAccessoryType:UITableViewCellAccessoryNone];
    }
    for(i=0;i<[tblProfileView numberOfRowsInSection:1];i++)
    {
        tt.row=i; tt.section=1;
        x=[tblProfileView cellForRowAtIndexPath:tt];
        [x setAccessoryType:UITableViewCellAccessoryNone];
    }

    x=[tblProfileView cellForRowAtIndexPath:indexPath];
    [x setAccessoryType:UITableViewCellAccessoryCheckmark];
    // Navigation logic may go here -- for example, create and push another view controller.
    // AnotherViewController *anotherViewController = [[AnotherViewController alloc] initWithNibName:@"AnotherView" bundle:nil];
    // [self.navigationController pushViewController:anotherViewController animated:YES];
    // [anotherViewController release];
}

【问题讨论】:

标签: iphone objective-c xcode uitableview


【解决方案1】:

我会跟踪应该检查的 data 并更改 tableView:didSelectRowAtIndexPath: 中的单元格并更新 tableView:cellForRowAtIndexPath: 中检查的数据,如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    // do usual stuff here including getting the cell

    // determine the data from the IndexPath.row

    if (data == self.checkedData)
    {
        cell.accessoryType = UITableViewCellAccessoryCheckmark;
    } else {
        cell.accessoryType = UITableViewCellAccessoryNone;
    }

    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    // determine the selected data from the IndexPath.row

    if (data != self.checkedData) {
       self.checkedData = data;
    }

    [tableView reloadData];
}

【讨论】:

  • 这不是马上做的,因为你调用了 reloadData (这可能很昂贵,具体取决于你的数据)。您可以简单地:让 cell = tableView.cellForRowAtIndexPath(indexPath) cell?.accessoryType = (yourTest) ? .复选标记:.None
  • 实际上你几乎必须同时做这两件事。按照 Max 指出的方式直接进行更新并在 cellForRowAtIndexPath 中配置单元格,否则当您滚动列表时,单元格状态会混淆。
  • 哦,同时实现 didDeselectRowAtIndexPath,这样您就可以再次取消选中单元格。
【解决方案2】:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{

    UITableViewCell *newCell = [tableView cellForRowAtIndexPath:indexPath];

    if (newCell.accessoryType == UITableViewCellAccessoryNone) {
        newCell.accessoryType = UITableViewCellAccessoryCheckmark;
    }else {
        newCell.accessoryType = UITableViewCellAccessoryNone;
    }


}

您还需要删除 cellForRowAtIndexPath 上的复选标记附件

if ([selectedOptionsArray indexOfObject:cell.textLabel.text] != NSNotFound) {
    cell.accessoryType = UITableViewCellAccessoryCheckmark;
}else{
    cell.accessoryType = UITableViewCellAccessoryNone;
}

【讨论】:

  • 这与 OP 要求的不同。没有提到允许多选或零选。当一个打开其他(S)必须关闭。您的解决方案允许用户自行打开和关闭一行,并且可能 selectedOptionsArray 存储多个选定的选项,而不是按要求存储一个。
  • @craig 是的,你是正确的。但我正在使用此代码来切换我的应用程序的选项(行)。我认为它可能有用,sn-p 有点基于 gerry3,但我没有使用 [tableview reloaddata]。
  • 感谢@palaniraja 我看到这篇文章正在寻找您的解决方案,所以我可以使用表格列表来选择项目。
  • 非常好的技巧。但我只有一个问题。我必须选择行两次才能取消选择它。猜猜为什么???
【解决方案3】:

声明一个名为prev的int变量并实现这个方法:-

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

 UITableViewCell *cell =[tableView cellForRowAtIndexPath:indexPath];

   if (cell.accessoryType==UITableViewCellAccessoryNone) 
   {
      cell.accessoryType=UITableViewCellAccessoryCheckmark;
      if (prev!=indexPath.row) {
         cell=[tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:prev inSection:0]];
         cell.accessoryType=UITableViewCellAccessoryNone;
         prev=indexPath.row;
     }

 }
 else{
     cell.accessoryType=UITableViewCellAccessoryNone;
 }
}

【讨论】:

  • 很好的答案,非常整洁。
  • 好答案,我在下面翻译成Swift。
【解决方案4】:

仅在选定行中实现复选标记逻辑的最短且最简单的方法.....


1.创建一个全局对象 NSIndexPath..

selectedIndexPathForCheckMark= [[NSIndexPath alloc] init];

2.在 didSelectRowAtIndexPath..

//将选中的indexPath赋给声明的对象

selectedIndexPathForCheckMark = indexPath;  
[tableView reloadData];

3.在 cellForRowAtIndexPath..

if ([selectedIndexPathForCheckMark isEqual:indexPath]) {
    [cell setAccessoryType:UITableViewCellAccessoryCheckmark];
}else {
    //setAccessoryType None if not get the selected indexPath
    [cell setAccessoryType:UITableViewCellAccessoryNone];
}

【讨论】:

    【解决方案5】:

    这是我如何使用静态单元格并绕过 cellForRow

    创建一个存储“已检查”单元格位置的 var。

     NSInteger _checkedCell;
    

    然后像这样实现willDisplayCelldidSelectRow 方法。

    - (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
        if (_checkedCell == indexPath.row) {
            cell.accessoryType = UITableViewCellAccessoryCheckmark;
        }
        else {
            cell.accessoryType = UITableViewCellAccessoryNone;
        }
    }
    
    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        _checkedCell = indexPath.row;
        [self.tableView reloadData];
    }
    

    【讨论】:

    • 虽然 NSInteger 的名称 checkedCell 可能会被误解为针对该单元格对象:)
    【解决方案6】:

    我知道这个问题已经很老了,但这里是基于 Blackberry 响应的 Swift 版本(顺便说一句,我已经投了赞成票)

    import UIKit
    
    class PlacesViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
    
        var placesArray = NSMutableArray()
        
        var previousCheckedIndex = 0
        
        override func viewDidLoad() {
            super.viewDidLoad()
    
            self.placesArray.addObject("Tandil")
            self.placesArray.addObject("Balcarce")
            self.placesArray.addObject("Mar del Plata")
            
            self.tableView.rowHeight = UITableViewAutomaticDimension
        }
    
        
        
        override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
            return self.placesArray.count
        }
        
        
        override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
            
            var cell: UITableViewCell = self.tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell
    
            cell.textLabel?.text = self.placesArray.objectAtIndex(indexPath.row) as? String
            
    
            return cell
        }
        
        
        override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    
            if (indexPath.row != previousCheckedIndex) {
                var cell: UITableViewCell = self.tableView.cellForRowAtIndexPath(indexPath)!
                if (cell.accessoryType == UITableViewCellAccessoryType.None) {
                    cell.accessoryType = UITableViewCellAccessoryType.Checkmark
                    if (previousCheckedIndex != indexPath.row) {
                        cell = tableView.cellForRowAtIndexPath(NSIndexPath(forRow: previousCheckedIndex, inSection: 0))!
                        cell.accessoryType = UITableViewCellAccessoryType.None
                        previousCheckedIndex = indexPath.row
                    }
                } else {
                    cell.accessoryType = UITableViewCellAccessoryType.None
                }
            
                tableView.reloadData()
            }
        }
    }

    【讨论】:

      【解决方案7】:

      在 Swift 2.0 中使用自定义的附件视图 uitableviewcell 和 swift

      1º 创建 Globar var IndexPath

      var indexSelected = NSIndexPath()
      

      2º 在 didSelectRowAtIndexPath 中

      func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
              indexSelected = indexPath
              TB_Lojas.reloadData()
          }
      

      cellForRowAtIndexPath 中的 3º:

      if SelectedIndexPath == indexPath {
                      let img = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
                      img.image = UIImage(named: "check")
                      cell.accessoryView = img
                  }else{
                      let img = UIImageView(frame: CGRect(x: 0, y: 0, width: 20, height: 20))
                      img.image = UIImage(named: "uncheck")
                      cell.accessoryView = img
                  }
      }
      

      【讨论】:

        【解决方案8】:

        考虑到您只想保持一个选择,并且如果您有自定义 UITableViewCell,我会推荐以下内容。

        在你的UITableViewController

        override func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
            //... 
            let data = dataArray[indexPath.row]
            if data.isSelected {
                tableView.selectRowAtIndexPath(indexPath, animated: false, scrollPosition: .None)
            }
            //...
        
            return cell
        }
        
        override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
            let data = dataArray[indexPath.row]
            data.isSelected = true
            let cell = tableView.cellForRowAtIndexPath(indexPath)
            cell?.setSelected(true, animated: true)
        }
        
        override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath) {
            let data = dataArray[indexPath.row]
            data.isSelected = false
            let cell = tableView.cellForRowAtIndexPath(indexPath)
            cell?.setSelected(false, animated: true)
        }
        

        在自定义UITableViewCell

        override func setSelected(selected: Bool, animated: Bool) {
            super.setSelected(selected, animated: animated)
        
            // Configure the view for the selected state
            self.accessoryType = .None
            if selected {
                self.accessoryType = .Checkmark
            }
        }
        

        只要不启用allowsMultipleSelection,它就会在选择新单元格时自动处理取消选择其他单元格。如果allowMultipleSelection 已启用,那么它也可以正常工作,只是您只需再次点击即可取消选择。

        【讨论】:

          【解决方案9】:

          BlackBerry 在 Swift 3 中的回答。带有标准单元格的 UITableView,选择 0 或 1 个单元格。

          private var previousSelection = NSIndexPath()
          
          func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
              tableView.deselectRow(at: indexPath, animated: true)
              let cell = tableView.cellForRow(at: indexPath)!
              if cell.accessoryType == .none {
                  cell.accessoryType = .checkmark
                  selection = indexPath
          
                  if previousSelection == IndexPath() {
                      previousSelection = indexPath
                  } else if previousSelection != indexPath {
                      let previousCell = tableView.cellForRow(at: previousSelection)
                      previousCell?.accessoryType = .none
                      previousSelection = indexPath
                  }
              } else if cell.accessoryType == .checkmark {
                  cell.accessoryType = .none
                  selection = IndexPath()
              }
          
          }
          

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-08-01
            • 2020-11-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多