我遇到一个问题,即在textField
中点击UITableViewCell
时,方法tableView:didSelectRowAtIndexPath:
不会被调用。问题是,我需要将我的tableView
滚动到正确的位置,否则键盘就会越过第一个响应者。
我必须像这样移动代码:
[[self tableView] scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
加入我的tableView
委托方法和我的UITextField
委托方法textFieldDidBeginEditing:
。
是创建新方法的最佳方法,将单击的单元格/文本字段的indexPath传递给它,并从tableView委托和UITextField
委托调用该方法?更好的办法吗?
答案 0 :(得分:22)
我发现以下效果很好(它假设您在表视图控制器中)
- (void)textFieldDidBeginEditing:(UITextField *)textField{
CGPoint pnt = [self.tableView convertPoint:textField.bounds.origin fromView:textField];
NSIndexPath* path = [self.tableView indexPathForRowAtPoint:pnt];
[self.tableView scrollToRowAtIndexPath:path atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
答案 1 :(得分:9)
有几种方法可以解决此问题。会发生的事情是tableViewCell将触摸事件委托给其子视图,这会导致文本字段处理触摸而不是您的单元格。
解决此问题:
将UITextfield的userinteractionEnabled属性设置为NO,然后当您获得didSelectRowAtIndexPath消息时,重新启用userInteractionEnabled并调用TextField的becomeFirstResponder。在v2.2上你甚至不需要设置userInteractionEnabled标志,我没有用其他版本测试过这个,但是文档很清楚你应该启用它。在tableViewController中,您只需要保存索引路径,直到获得UIKeyboardDidShow消息
为UITextField创建一个委托,该委托报告回tableViewController,以便您可以从那里设置滚动偏移。
注册键盘事件,然后通过检查编辑模式中的文本字段来确定scrolloffset
答案 2 :(得分:6)
您可以将控制器设置为UITextField的代理,然后在textFieldDidBeginEditing:
或textFieldShouldBeginEditing:
答案 3 :(得分:3)
我没有在网上找到任何适合我的解决方案。经过几天的谷歌搜索和实验,我终于把这个发布好了。这是Apple iPhone中的复杂错误,您将在本文末尾看到。
如果你遇到像我这样的问题如下:
让tableviewcell大于iphone屏幕的一半(不要与Apple的UICatalog的例子混淆,有一个不到50分的短tableview单元,这里不适用。),
在单元格中有多个uitexfields或uitextfield和uitextview或uiwebview的组合,
在uitextfields和uitextview或uiwebview之间点击会导致无法预测的滚动位置,点击的uitextfield会跳出视图或被keybaord覆盖。它仅在键盘出现在tableviewcell中时才第一次工作,并且随后无法正常工作。
在阅读与此类似的帖子后,我有了重大突破:http://alanduncan.net/old/index.php?q=node/13他们也没有完全正确。痛苦是由UIKeyboard事件中的错误引起的。当键盘首次出现时,它会发出UIKeyboardWillShowNotification和UIKeybaordDidShowNotification。 Theree是iPhone中的一个错误,不知何故,第一个UIKeyboardWillShowNotification与随后的UIKeyboardWillShowNotification不同。解决方案是OBSERVE UIKeyboardDidShowNotification。因此,当您的单元格出现时,请添加以下代码
NSNotificationCenter*nc=[NSNotificationCenter defaultCenter];
[nc addObserver:self selectorselector(keyboardDidShow name:UIKeyboardDidShowNotification object:self.window];
在keyboardDidShow函数中,我们需要滚动TABLEVIEW,而不是像上面帖子中建议的tableviewcell。或者您可能会看到各种对象分开,而不是一起滚动。
(void)keyboardDidShow:(NSNotification *)notif
{
//1. see which field is calling the keyboard
CGRect frame;
if([textField_no1 isFirstResponder])
frame=textField_no1.frame;
else if([textField_no2 isFirstResponder])
frame=textField_no2.frame;
else if([textField_no3 isFirstResponder])
frame=textField_no3.frame;
else if([textView isFirstResponder])
frame=textView.frame;
else return;
CGRect rect=self.superview.frame;
//2. figure out how many pixles to scroll up or down to the posistion set by theKeyBoardShowUpHorizon.
//remove the complexity when the tableview has an offset
[((UITableView*)[self.superview).setContentOffset:CGPointMake(0,0) animated:YES];
int pixelsToMove=rect.origin.y+ frame.origin.y-theKeyBoardShowUpHorizon;
//3. move the uitableview, not uitableviewcell
[self moveViewUpOrDownByPixels:pixelsToMove];
}
- (void)moveViewUpOrDownByPixels:(int)pixels
{
[UIView beginAnimations:nil context:NULL];
[UIView setAnimationDuration:0.6];
//find the position of the UITableView, the superView of this tableview cell.
CGRect rect=self.superview.frame;
//moves tableview up (when pixels >0) or down (when pixels <0)
rect.origin.y -= pixels;
rect.size.height += pixels;
self.superview.frame = rect;
[UIView commitAnimations];
}
要恢复tableView,你需要在UIKeyboardDidHideNotification上添加观察者(不是其他帖子建议的UIKeyboardWillHideNotification,以避免闪烁),每次你都会出现tableviewcell,并将tableview放回原处。
[nc addObserver:self selectorselector(keyboarDidHide) name:UIKeyboardDidHideNotification object:nil];
- (void)keyboardDidHideNSNotification*)notif
{
//we have moved the tableview by number of pixels reflected in (self.superview.frame.origin.y). We need to move it back
[self moveViewUpOrDownByPixels:self.superview.frame.origin.y];
}
不要忘记在[[NSNotificationCenter defaultCenter] removeObserver删除单元格消失时删除两个观察者:...
这就是全部。我希望苹果iPhone团队有一天会解决这个问题,可能会在几个月内解决这个问题。
答案 4 :(得分:3)
我找到了解决方案。
<强>代码强>
-(void) textFieldDidBeginEditing:(UITextField *)textField
{
UITableViewCell *cell = (UITableViewCell *) [[textField superview] superview];
[self.tableView scrollToRowAtIndexPath:[tableView indexPathForCell:cell]
atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
答案 5 :(得分:3)
我发现实际上很容易做到这一点。
UITextField委托方法textFieldDidBeginEditing将为您提供文本字段,然后您可以使用以下方法将其映射到indexPath:
self.currentIndexPath = [self.tableView indexPathForRowAtPoint:textField.frame.origin];
然后您可以将单元格滚动到视图中(即在您的UIKeyboardDidShowNotification键盘通知处理程序中):
[self.tableView scrollToRowAtIndexPath:self.currentIndexPath atScrollPosition:UITableViewScrollPositionNone animated:YES];
答案 6 :(得分:1)
不会为UITextField嵌入单元格调用didSelectRowAtIndexPath;因此,滚动逻辑需要在其他地方。
- (void)textFieldDidBeginEditing:(UITextField *)textField {
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:0 inSection:1];
UITableViewCell *cell = [_tableView cellForRowAtIndexPath:indexPath];
[_tableView setContentOffset:CGPointMake(0, cell.frame.size.height) animated:YES];
}
确保将textField委托连接到自己
答案 7 :(得分:0)
注册UIKeyboardWillShowNotification和UIKeyboardWillHideNotification,然后根据需要在通知处理程序中调整视图。其中一个示例应用程序显示了如何执行此操作,但我忘记了哪些... SQLiteBooks,或者EditableDetailView。
答案 8 :(得分:0)
我正在努力解决同样的问题,我在UITableViewCells中有UITextFields,并且在编辑时无法获得视图滚动到该字段。我的解决方案的核心如下。
此代码的关键是创建UITextField的行。它不是在CGRectMake()函数中对x和y值进行硬编码,而是使用放置它的单元格中的x和y(+/-你希望从单元格边缘得到的任何偏移量,如下所示)。 UITextField *中的硬编码x和y值为每个单元格提供每个UITextField *的相同的 x,y帧位置(当显示时,它显然被单元格框覆盖),因此当您调用' scrollRectToVisible'代码它似乎没有正确的坐标,它应滚动。
1)创建单元格,并使用单元格的框架x和y值将UITextField *添加到单元格(我在这里包括可选的偏移
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell* cell;
cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:@"UITableViewCell"] autorelease];
//this is the critical part: make sure your UITextField* frame is based on the frame of the cell in which it's being placed.
UITextField* txtField = [[UITextField alloc] initWithFrame:CGRectMake(cell.frame.origin.x+20, cell.frame.origin.y+9, 280, 31)];
txtField.delegate = self;
[cell addSubview:txtField];
return cell;
}
2)调整textFieldDidBeginEditing
中的滚动视图-(void) textFieldDidBeginEditing:(UITextField *)textField {
CGRect textFieldRect = [textField frame];
[self.tableView scrollRectToVisible:textFieldRect animated:YES];
}
答案 9 :(得分:0)
由于没有简单的方法可以确定用户是否点击了文字字段或是通过becomeFirstResponder
激活了这个问题,这个问题更加严重。
我能想出的最优雅的解决方案是在单元子类上实现hitTest:withEvent:
,并且在选择单元格之前基本上假装文本字段不存在。
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
UIView *view = [super hitTest:point withEvent:event];
if(view == self.textField && !self.selected) {
return self;
}
return view;
}
tableView:didSelectRowAtIndexPath:
然后应手动将文本字段作为第一响应者。
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
TextFieldCell* cell = [self.tableView cellForRowAtIndexPath:indexPath];
[cell.textField becomeFirstResponder]
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
最后,我们必须在完成编辑后取消选择该行。这可以通过UITextField委托或通过键盘通知完成,无论您喜欢什么。
- (void)textFieldDidEndEditing:(UITextField *)textField {
[self.view endEditing:YES];
}
答案 10 :(得分:0)
我们有一个名为TPKeyboardAvoiding的控制器,它处理了有关tableview和scrollview的动态自动滚动的所有内容。 您可以从下面的代码下载示例代码。 https://github.com/NarayanaRao35/TPKeyboardAvoiding