iOS6和屏幕外的UITextView在UITableView
我有一个UITableViewController在每个单元格中都有一个UITextField。当用户点击一个字段返回,它会自动将下一个字段是第一个响应并滚动表显示领域,像这样:iOS6和屏幕外的UITextView在UITableView
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
UITextField *nextTextField=nil;
NSInteger row;
NSInteger section;
if(textField == self.txtFieldA)
{
nextTextField = self.txtFieldB;
row=1; section=0;
}
else if(textField == self.txtFieldB)
{
nextTextField = self.txtFieldC;
row=2; section=0;
}
else
{
[textField resignFirstResponder];
}
if(nextTextField)
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:section];
[nextTextField becomeFirstResponder];
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES];
}
}
当您选择文本字段中的问题来(说txtFieldA ),向下滚动表格以便txtFieldB不可见,然后按Enter键。它在iOS5上按预期工作(txtFieldB成为新的第一响应者)。但是,在iOS6上它没有。它滚动到表格中的正确位置,但txtFieldB不成为第一响应者(我不确定是什么 - 当我在导航控制器上点击“返回”时,键盘保持可见状态)。
当我点击“返回”时,txtFieldB的didBeginEditing未被触发。如果我将[nextTextField becomeFirstResponder]
延迟了一秒钟左右(直到滚动动画完成,这使得nextTextField可见),它的工作方式与预期的一样,但它看起来很乱,不那么流畅,所以我宁愿明白发生什么事情比实现类似的东西。
在我对这个问题的解决方案中,我将UITableViewCell分类为一个文本字段单元格。在该文本字段单元格中,我覆盖了-setSelected:animated:
。
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
if (selected) {
[self.textField becomeFirstResponder];
}
}
早在我的视图控制器,当我要前进到下一个领域,我只是在选择它的行。
- (IBAction)advanceToNextTextField
{
NSIndexPath *indexPath = [self nextIndexPathFromIndexPath:self.indexPathOfActiveField];
[self.tableView selectRowAtIndexPath:indexPath
animated:YES scrollPosition:UITableViewScrollPositionNone];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionNone animated:YES];
}
这使得处理返回键容易。
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
switch (textField.returnKeyType) {
case UIReturnKeyNext: [self advanceToNextTextField]; break;
case UIReturnKeyDone: [self resignFirstResponder]; break;
default: break;
}
return YES;
}
希望有所帮助。
我还有一个现有的项目,在iOS 6之前工作正常。我的通用应用程序使用UITableView
在键盘工具栏(类似于Safari)上创建带有“下一个”和“上一个”按钮的窗体。该表显示包含文本字段的UITableViewCell
子类的实例。下一个/上一个功能也会打包 - 因此最后一个字段的“下一个”会将焦点返回到表单的顶部。
不幸的是,杰弗里托马斯的解决方案并不适合我。如果单元格不在屏幕上,则advanceToNextField方法中的select-and-scroll方法对单元格本身工作良好。在setSelected
方法中,文本字段的视图层次结构是正确的:UITextField
- >UITableViewCellContentView
- >UITableViewCell
子类 - >UITableView
。
然而,becomeFirstResponder
调用仍然未能激活该字段的编辑模式,消防textFieldDidBeginEditing
等的键盘仍然是可见的,但不会影响现在可见的细胞。
现在,我已经能够绕过这个问题是滚动第一没有动画的唯一途径:
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
[self.tableView selectRowAtIndexPath:indexPath animated:YES scrollPosition:UITableViewScrollPositionNone];
像运Ned的延时技术,这保证了文本字段在应用程序要求它做出响应时可见。否则,看起来becomeFirstResponder
在动画&期间正在触发文本字段(完全)可见之前。显然iOS 6中的一些更改对第一响应消息和可见性更严格!
不幸的是,当从一个领域移动到另一个领域时,这会失去很好的流体动画。假设这不仅仅是iOS 6.0中的一个bug,我打算在将来使用UITableView
作为一种形式。
在我的同事Charles的帮助下找到了解决这个问题的方法(谢谢!)。我也尝试过杰弗里托马斯的解决方案(以及它的变体),但没有运气:如果其表格单元格在屏幕外,文本字段不会成为第一响应者,如Ogel所述。我寻找UITableViewDelegate
方法,当桌面视图完成动画时会提醒我,并延迟调用文本字段的setSelected:
方法,直到那时,没有运气。然后他向我指出
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView
也由表视图(UITableViewDelegate
符合UIScrollViewDelegate
),当它完成滚动响应表视图方法
- (void)scrollToRowAtIndexPath:(NSIndexPath *)indexPath atScrollPosition:(UITableViewScrollPosition)scrollPosition animated:(BOOL)animated
所以关键在于解雇计算你打算在你的下一个/上一个方法来选择该行的索引路径(如杰弗里·托马斯的- (IBAction)advanceToNextTextField
法),但不是选择它,只需滚动到它,并为它伊娃:
[_table scrollToRowAtIndexPath:nextIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
_selectIndexPathOnAnimationEnd = nextIndexPath;
然后在滚动视图的委托方法,在该指数的路径选择该行表视图已经完成滚动之后:
- (void)scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView {
if(_selectIndexPathOnAnimationEnd != nil) {
[_table selectRowAtIndexPath:_selectIndexPathOnAnimationEnd animated:NO scrollPosition:UITableViewScrollPositionMiddle];
_selectIndexPathOnAnimationEnd = nil;
}
}
此时文本字段可以成为第一个响应者。
这绝对是一种更好的方式来设置它,但我不确定这将解决在下一个单元离开屏幕时点击“下一步”的问题。当您在iOS6上编译代码时,此代码是否工作? – Ned
是的,它适用于iOS6。此代码直接从我的应用程序中拉出,该应用程序旨在运行iOS5和iOS6。 –