UITableViewCell 与 UITextField 失去选择 UITableView 行的能力?
Posted
技术标签:
【中文标题】UITableViewCell 与 UITextField 失去选择 UITableView 行的能力?【英文标题】:UITableViewCell with UITextField losing the ability to select UITableView row? 【发布时间】:2011-07-05 08:36:08 【问题描述】:我几乎完成了实现一个带有UITextField
的UITableViewCell
。而不是通过CGRectMake
和UITableViewCell.contentView
我已经实现了它更简单的方式:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"Cell"];
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
amountField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 190, 30)];
amountField.placeholder = @"Enter amount";
amountField.keyboardType = UIKeyboardTypeDecimalPad;
amountField.textAlignment = UITextAlignmentRight;
amountField.clearButtonMode = UITextFieldViewModeNever;
[amountField setDelegate:self];
[[cell textLabel] setText:@"Amount"];
[cell addSubview:amountField];
return cell;
然后我还实现了didSelectRow
方法,将 textField 重新签名以允许显示其他字段的输入视图。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
...
[amountField resignFirstResponder];
...
这很顺利,唯一的问题是表格中还有其他行,当其他行被选中时,整个单元格被选中并变为蓝色,而我的 UITextField 没有,我的意思是该字段被选中并且我可以输入文本但单元格未被选中。 我已经测试过了,发现问题出在这条线上:
[cell addSubview:amountField];
这似乎破坏了可选择的单元格行为,甚至将其添加到[cell contentView]
也无法解决此问题。我错过了什么吗?
【问题讨论】:
【参考方案1】:如果文本字段的 userInteractionEnabled 设置为 YES,并且它填满了整个单元格,则无法让单元格监听触摸。为了让单元格响应触摸,您需要将文本字段的 userInteractionEnabled 设置为 NO。
编辑:如果你想让文本字段可编辑,当单元格被选中时,在didSelectRowAtIndexPath:方法中添加以下代码,
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
// get the reference to the text field
[textField setUserInteractionEnabled:YES];
[textField becomeFirstResponder];
【讨论】:
如果你设置userInteractionEnabled = NO;
这不会使 UITextField 不可编辑吗?
显然不是:我已遵循 EmptyStack 的建议并设置 [amountField setUserInteractionEnabled:NO];在 DidSelectRow 方法的开头,然后 [amountField setUserInteractionEnabled:YES] 仅当所选行是带有文本字段的行时。选择现在可以了,但我必须在该行上点击两次才能实际输入文本...
@micpringle,当然。当文本字段填充单元格时,他不能同时让文本字段和单元格响应触摸。
@Fabrizio Prosperi,您无需在单元格上点击两次。您可以在didSelectRowAtIndexPath:
方法中的[amountField setUserInteractionEnabled:YES]
行之后调用[amountField becomeFirstResponder]
。
感谢 EmptyStack 成功了,您的解决方案在这里最简单且运行顺利!【参考方案2】:
添加子视图并没有破坏任何内容,而是 UITextField 在 UITableViewCell 之前捕获触摸。您可以通过在 UITextField 之外但在 UITableViewCell 范围内点击来测试它,您会发现它实际上仍然按照您的预期进行选择。
要解决这个问题,您可以继承 UITextField 并添加一个 UITableView 属性。在实例化 UITextField 并将其添加到单元格时设置属性。
amountField.tableView = tableView;
然后你需要在你的子类中重写 becomeFirstResponder,并在方法中使用 UITextField 获取单元格的行,然后手动选择它
- (BOOL)becomeFirstResponder
// Get the rect of the UITextView in the UITableView's coordinate system
CGRect position = [self convertRect:self.frame toView:self.tableView];
// Ask the UITableView for all the rows in that rect, in this case it should be 1
NSArray *indexPaths = [self.tableView indexPathsForRowsInRect:position];
// Then manually select it
[self.tableView selectRowAtIndexPath:[indexPaths objectAtIndex:0] animated:YES scrollPosition:UITableViewScrollPositionNone];
return YES;
【讨论】:
这也有效,但它需要很多额外的代码,而按照 EmptyStack 下面的建议设置文本字段 userInteractionEnabled=NO 是几行代码......至少在我找到之前其他一些问题:) 谢谢你的帮助,它使问题更清楚了。 这不是保留循环吗?tableView
-> visibleCells
-> amountField
-> tableView
@jakenberg true,amountField
上的 tableView
属性应指定为 weak
以避免潜在的保留周期
别忘了打电话给[super becomeFirstResponder];【参考方案3】:
第一件事是您没有使用可重复使用的单元格。您提供的编码会占用大量内存。
接下来您可以通过触摸文本字段以外的区域来选择行。
您的问题的一个解决方案是
在您的文本字段代表中
UITableViewCell *cell = (UITableViewCell *)[textField superView];
cell.selected=YES; //I think this will call the didSelectRowATIndex;
我不确定这是否可行。不过值得一试。
【讨论】:
除了这个表是 4 个单元格只是因为它是一个很好的输入掩码,所以内存不应该是一个大问题,但你为什么说我没有使用可重复使用的单元格?我以为我做到了。我现在要试试你的解决方案。谢谢。 我认为您误解了可重复使用的概念。请参见此处developer.apple.com/library/ios/#documentation/UserExperience/…... 无论如何 4 个单元格是可以的,但如果一行超过 10 个单元格就会给您带来问题。 我当然可能误解了,但是当单元格内部都有不同的控件时,是否应该避免重复使用单元格?无论如何感谢您的链接:) 我也尝试了您的解决方案,在 textFieldShouldBeginEditing 中实现,它可以工作,但需要其他代码在选择其他单元格时取消选择单元格。无论如何是一个很好的提示。谢谢。【参考方案4】:首先你需要为cellForRowAtIndexPath使用reuseIdentifier,如果你不使用reuseIdentifier的原因是:当你上下滚动时,它总是会分配新的单元格和新的文本字段,所以你需要把cell==nil条件,所以修改后的代码在这里:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *reuseIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (cell==nil)
cell = [[[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseIdentifier] autorelease];
UITextField *amountField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 190, 30)];
amountField.placeholder = @"Enter amount";
amountField.keyboardType = UIKeyboardTypeDecimalPad;
amountField.textAlignment = UITextAlignmentRight;
amountField.clearButtonMode = UITextFieldViewModeNever;
[amountField setDelegate:self];
[cell.contentView addSubview:amountField];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
[[cell textLabel] setText:@"Amount"];
return cell;
在 didSelect 委托方法中你可以这样做
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
[prevField resignFirstResponder];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIView *view = [[cell.contentView subviews] lastObject];
if([view isKindOfClass:[UITextField class]]
currentField = (UITextField*)view;
[currentField becomeFirstResponder];
prevField = currentField;
【讨论】:
伙计们,我感谢您为教授 Cocoa 最佳实践所做的努力,但我试图将唯一相关的代码放在那里,amountField 不是每次都实例化,而是仅在视图中加载,检查 !cell 是在那里,但我省略了,因为与我的问题无关,而且我的表格不会滚动,因为它只有 4 行。不过,其余的 cmets 非常有帮助。谢谢!【参考方案5】:在索引路径行的单元格内添加以粗体给出的这一行,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"Cell"];
[cell setSelectionStyle:UITableViewCellSelectionStyleBlue];
amountField = [[UITextField alloc] initWithFrame:CGRectMake(110, 10, 190, 30)];
amountField.placeholder = @"Enter amount";
amountField.keyboardType = UIKeyboardTypeDecimalPad;
amountField.textAlignment = UITextAlignmentRight;
amountField.clearButtonMode = UITextFieldViewModeNever;
[amountField setDelegate:self];
[[cell textLabel] setText:@"Amount"];
**for (UIView *cellSubViews in cell.subviews)
cellSubViews.userInteractionEnabled = NO;
**
[cell addSubview:amountField];
return cell;
试试这个,它会起作用的
【讨论】:
以上是关于UITableViewCell 与 UITextField 失去选择 UITableView 行的能力?的主要内容,如果未能解决你的问题,请参考以下文章
UITableViewCell 与 UITextField 失去选择 UITableView 行的能力?
自定义uitableviewcell时,registerNib与registerClass的区别(转载)
UIMenucontroller 与 uitableviewcell 上的 uitextview
UITableViewCell 中的 UIStackView 与多行 UILabel