我在UICollectionViewCell
内部有一个可以收到第一响应者状态的文本字段。单元格当前在屏幕上不可见,我想根据UISegmentedControl
按下的按钮滚动到单元格。此控件有两个段......对第二个段的命中应该滚动到UICollectionView
的第二个区域中的第一个单元格。发生这种情况后,应该以编程方式选择单元格,然后该单元格内的文本字段应该获得第一响应者状态并调出键盘。
现在发生的事情(在我的动作方法中,来自分段控件的值更改)是对-[UICollectionView selectItemAtIndexPath:animated:scrollPosition:]
的调用根本没有滚动到它(我正在使用UICollectionViewScrollPositionTop
;也可以是“…None
”)。如果我手动向下滑动列表,则确实选择了单元格(在该状态下它会获得较暗的背景颜色),但文本字段当然没有第一响应者状态。
为了解决滚动问题,我已经能够确定列表中单元格的位置,并滚动到单元格的内容偏移量(我在这里也使用了scrollRectToVisible
)。然后我手动选择它(以及告诉委托也启动它的适当方法,单元格的文本字段获得第一响应者状态)。
- (void)directionSegmentedControlChanged:(UISegmentedControl *)sender {
NSIndexPath *path = [NSIndexPath indexPathForItem:0 inSection:sender.selectedSegmentIndex];
UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:path];
[self.collectionView setContentOffset:attributes.frame.origin animated:YES];
[self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self.collectionView.delegate collectionView:self.collectionView didSelectItemAtIndexPath:path];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
BDKCollectionViewCell *cell = (BDKCollectionViewCell *)[collectionView cellForItemAtIndexPath:indexPath];
[cell.textField becomeFirstResponder];
}
这里的问题是在-[collectionView:didSelectItemAtIndexPath:]
中看到的单元格是nil,因为当方法被触发时,它不在集合视图的可见单元格集中。
解决这个问题的最佳方法是什么?我已经尝试在[UIView animateWithDuration:animations:completion:]
块中抛出我的滚动代码,并在完成后分配第一个响应者,但是以这种方式手动设置集合视图动画忽略了加载应该滚动过去的任何单元格。有什么想法吗?
更新:非常感谢@Esker,他建议我在使用Grand Central Dispatch延迟后执行“焦点选择”操作。我的解决方案最终看起来像这样。
- (void)directionSegmentedControlChanged:(UISegmentedControl *)sender {
NSIndexPath *path = [NSIndexPath indexPathForItem:0 inSection:sender.selectedSegmentIndex];
UICollectionViewLayoutAttributes *attributes = [self.collectionView layoutAttributesForItemAtIndexPath:path];
[self.collectionView setContentOffset:attributes.frame.origin animated:YES];
dispatch_time_t startAfter = dispatch_time(DISPATCH_TIME_NOW, 0.28 * NSEC_PER_SEC);
dispatch_after(startAfter, dispatch_get_main_queue(), ^{
[self.collectionView selectItemAtIndexPath:path animated:NO scrollPosition:UICollectionViewScrollPositionNone];
[self collectionView:self.collectionView didSelectItemAtIndexPath:path];
});
}
答案 0 :(得分:1)
我对UITableView
进行了类似的挑战:滚动到尚未显示的单元格,并在目标单元格中可见时将第一响应者分配给目标单元格中的UITextField
。这是我如何处理这个的简化描述。我想这种方法适用于UICollectionView
,但我对集合视图没有多少经验。
becomeFirstResponder
,然后根据需要滚动到该单元格。collectionView:cellForItemAtIndexPath:
中,您可以尝试检查该属性,以查看给定indexPath
的文本字段是否需要获得焦点,如果是,请立即发送becomeFirstResponder
,但我发现如果单元格滚动到视图中这将不起作用,可能是因为此时,当您配置新单元格时,它实际上还不在视图层次结构中。所以我添加了一张支票,如果becomeFirstResponder
此时返回NO
,我会在延迟后再试一次:dispatch_after(someDelay, dispatch_get_main_queue(), ^(void){
[self getFocus:textField];
});
getFocus
方法会将becomeFirstResponder
发送到文本字段,并清除跟踪哪个文本字段需要关注的属性。
我的实际实现有点专门用于与我的表视图关联的视图模型,并封装在几个类中并使用一些KVO,但我想避免这种情况,并专注于上述描述中所需的最小逻辑。 / p>