UITableView 每个单元格中有多个项目
Posted
技术标签:
【中文标题】UITableView 每个单元格中有多个项目【英文标题】:UITableView with multiple items in each cell 【发布时间】:2011-03-21 15:42:03 【问题描述】:我有一个表格视图,我试图在其中放置一个带有图像和标签的按钮。我想在单击后更改按钮的图像。
代码如下:
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
checkedImg = [UIImage imageNamed:@"buttonUnChecked1.png"];
UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
//Set up the cell...
NSString *cellValue = [suggestions objectAtIndex:indexPath.row];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
check = [UIButton buttonWithType:UIButtonTypeCustom];
check.frame=CGRectMake(0,35,20,20);
[check setImage:checkedImg forState:UIControlStateNormal];
[check addTarget:self action:@selector(checkClicked:) forControlEvents: UIControlEventTouchUpInside];
[cell.contentView addSubview:check];
cellContent = [[UILabel alloc]initWithFrame:CGRectMake(40,32,500,25)];
cellContent.text = cellValue;
[cell.contentView addSubview:cellContent];
return cell;
-(void)checkClicked:(UIButton *)b
checkedImg = [UIImage imageNamed:@"buttonChecked1.png"];
[check setImage:checkedImg forState:UIControlStateNormal];
通过这样做,按钮的图像会发生变化,但只有最后一个而不是单击的那个。我知道它背后的原因,但我不知道如何实现我想要的。
【问题讨论】:
【参考方案1】:获得所需结果的结构化方式:
为表格单元格创建一个 UIView 子类(包含按钮和标签)。您实例化这些自定义视图并将它们设置为您的contentView
用于cellForRowAtIndexPath
中的每个表格单元格。
您的每个自定义视图都会监听自己的按钮是否被按下。当它被按下时,它会切换其状态并告诉主视图控制器(通过委托方法)它已被切换。主视图控制器在有问题的单元格上调用 reloadData 以使其以正确的外观重新加载。
请注意,这种方法要求您告诉每个自定义视图它在表中呈现哪个索引路径——这样它就可以通知主视图控制器的委托方法——需要这个信息来触发重新加载合适的单元格。
顺便说一句,我假设您想在用户完成编辑后查看表格中按钮的状态,而您当前的方法并没有非常明确地捕获状态内容——您必须迭代您的按钮,或将选定的项目添加到可变数组,或其他东西。
【讨论】:
【参考方案2】:解决您的问题的简单方法是将您的 checkClicked:
方法更改为:
-(void)checkClicked:(UIButton *)b
[b setImage:[UIImage imageNamed:@"buttonChecked1.png"] forState:UIControlStateNormal];
但是你也应该调整你的 tableView:cellForRowAtIndexPath:
方法以避免重复创建按钮并清理一些内存问题,例如:
- (UITableViewCell *)tableView:(UITableView *)_tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [_tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIButton *checkBtn = [UIButton buttonWithType:UIButtonTypeCustom];
checkBtn.frame = CGRectMake(0,35,20,20);
[checkBtn setImage:[UIImage imageNamed:@"buttonUnChecked1.png"]; forState:UIControlStateNormal];
[checkBtn addTarget:self action:@selector(checkClicked:) forControlEvents: UIControlEventTouchUpInside];
[cell.contentView addSubview:checkBtn];
UILabel *cellContentLbl = [[UILabel alloc]initWithFrame:CGRectMake(40,32,500,25)];
cellContentLbl.tag = 1;
[cell.contentView addSubview:cellContentLbl];
[cellContentLbl release];
//Set up the cell...
NSString *cellValue = [suggestions objectAtIndex:indexPath.row];
cellContent = (UILabel *)[cell viewWithTag:1];
cellContent.text = cellValue;
return cell;
【讨论】:
这段代码不会无法重置重复使用的单元格的状态吗?如果单击单元格的按钮,然后滚动,单击的按钮将出现在不应出现的位置。 非常感谢@theChrisKent 但是还有一个问题,如果用户再次点击它,它应该再次取消选中。为此,我将我的 checkClicked 方法更改为:-(void)checkClicked:(UIButton *)b if (!checked) [b setImage:checkedImg forState:UIControlStateNormal];检查=是; else [b setImage:unCheckedImg forState:UIControlStateNormal];但是现在,如果用户取消选中一个按钮并单击另一个按钮后,由于 Bool 值更改为 YES,它不起作用。 @Ashutosh 我的回答只解决了您眼前的问题,并没有解决您所有设计的问题。您正在尝试为多个对象/值保留单个变量,这将永远不会起作用。您不能为所有按钮或单个按钮引用使用单个checked
值,因为这两个都将仅指向最后一个检查或创建(分别)。 @Occulus 的答案更好,因为它解决了真正的问题——你的设计。请接受他的回答(尽管请随意给我一个赞成票 :))并与他一起找出更好的解决方案。
回复:我之前关于未能重置重复使用的单元格状态的评论——请参阅 UITableViewCell 中的 prepareForReuse 方法,了解一个很好的方法。以上是关于UITableView 每个单元格中有多个项目的主要内容,如果未能解决你的问题,请参考以下文章
从多节 UITableView 中的自定义静态单元格中检索标签文本
如何从自定义 UITableview 中检索有关选择单元格的数据