草庐IT

ios - UICollectionView:激活、滚动并将第一响应者分配给远程单元格

coder 2023-09-29 原文

我在 UICollectionViewCell 中有一个文本字段,可以接收第一响应者状态。该单元格当前在屏幕上不可见,我想根据从 UISegmentedControl 中点击的按钮滚动到该单元格。这个控件有两个部分……点击第二个部分应该滚动到 UICollectionView 第二部分的第一个单元格。发生这种情况后,应该以编程方式选择单元格,然后该单元格内的文本字段应该获得第一响应者状态并调出键盘。

现在发生的事情(在我的操作方法中,来自分段控件的值更改)是对 -[UICollectionView selectItemAtIndexPath:animated:scrollPosition:] 的调用根本没有滚动到它(我正在使用 UICollectionViewScrollPositionTop;也可能是“…None”)。如果我手动按下列表,该单元格确实被选中(在该状态下它的背景颜色更深),但文本字段肯定没有第一响应者状态。

为了解决滚动问题,我已经能够确定单元格在列表中的位置,并滚动到单元格的内容偏移量(我在这里还使用了 scrollRectToVisible)。然后我手动选择它(并告诉委托(delegate)人也触发其适当的方法,其中单元格的文本字段获得第一响应者状态)。

- (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,因为当方法被触发时它不在 Collection View 的可见单元格集中。

解决这个问题的最佳方法是什么?我尝试将我的滚动代码放入 [UIView animateWithDuration:animations:completion:] block 中,并在完成时分配第一响应者,但以这种方式手动设置 Collection View 的动画会忽略加载任何应该滚动过去的单元格。有什么想法吗?


更新:非常感谢@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];
    });
}

最佳答案

我在 UITableView 中遇到了类似的挑战:滚动到一个尚不可见的单元格,并在它出现后将第一响应者分配给目标单元格中​​的 UITextField可见的。这是我如何处理这个的简单描述。我想这种方法可以与 UICollectionView 一起使用,但我对 Collection View 没有太多经验。

  1. 如果所需的单元格/文本字段当前可见,立即将其发送给 becomeFirstResponder,并根据需要滚动到该单元格。
  2. 否则,在 View Controller 或类似类中设置一个属性,指示文本字段需要焦点,以及哪个需要焦点
  3. 告诉 TableView / Collection View 滚动到所需的索引路径
  4. collectionView:cellForItemAtIndexPath: 中,您可以尝试检查该属性以查看给定 indexPath 处的文本字段是否需要获得焦点,如果需要,请发送它 becomeFirstResponder 立即,但我发现如果单元格正在滚动到 View 中,这将不起作用,大概是因为此时,当您配置新单元格时,它实际上还不在 View 层次结构中.所以我加了一个检查,如果此时becomeFirstResponder返回NO,我延迟后再试:
dispatch_after(someDelay, dispatch_get_main_queue(), ^(void){
    [self getFocus:textField];
});

getFocus 方法会将 becomeFirstResponder 发送到文本字段并清除跟踪哪个文本字段需要焦点的属性。

我的实际实现在某种程度上专门针对与我的 TableView 关联的 View 模型,并封装在几个类中并使用了一些 KVO,但我想避免这种情况,并专注于上面描述中所需的最少逻辑。

关于ios - UICollectionView:激活、滚动并将第一响应者分配给远程单元格,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17435805/

有关ios - UICollectionView:激活、滚动并将第一响应者分配给远程单元格的更多相关文章

  1. ruby - 如何验证 IO.copy_stream 是否成功 - 2

    这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下

  2. ruby-on-rails - 每次我尝试部署时,我都会得到 - (gcloud.preview.app.deploy) 错误响应 : [4] DEADLINE_EXCEEDED - 2

    我是Google云的新手,我正在尝试对其进行首次部署。我的第一个部署是RubyonRails项目。我基本上是在关注thisguideinthegoogleclouddocumentation.唯一的区别是我使用的是我自己的项目,而不是他们提供的“helloworld”项目。这是我的app.yaml文件runtime:customvm:trueentrypoint:bundleexecrackup-p8080-Eproductionconfig.ruresources:cpu:0.5memory_gb:1.3disk_size_gb:10当我转到我的项目目录并运行gcloudprevie

  3. Ruby 文件 IO 定界符? - 2

    我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的

  4. python - 如何读取 MIDI 文件、更改其乐器并将其写回? - 2

    我想解析一个已经存在的.mid文件,改变它的乐器,例如从“acousticgrandpiano”到“violin”,然后将它保存回去或作为另一个.mid文件。根据我在文档中看到的内容,该乐器通过program_change或patch_change指令进行了更改,但我找不到任何在已经存在的MIDI文件中执行此操作的库.他们似乎都只支持从头开始创建的MIDI文件。 最佳答案 MIDIpackage会为您完成此操作,但具体方法取决于midi文件的原始内容。一个MIDI文件由一个或多个音轨组成,每个音轨是十六个channel中任何一个上的

  5. Get https://registry-1.docker.io/v2/: net/http: request canceled while waiting - 2

    1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里

  6. ruby-on-rails - 在 Ruby on Rails 中发送响应之前如何等待多个异步操作完成? - 2

    在我做的一些网络开发中,我有多个操作开始,比如对外部API的GET请求,我希望它们同时开始,因为一个不依赖另一个的结果。我希望事情能够在后台运行。我找到了concurrent-rubylibrary这似乎运作良好。通过将其混合到您创建的类中,该类的方法具有在后台线程上运行的异步版本。这导致我编写如下代码,其中FirstAsyncWorker和SecondAsyncWorker是我编写的类,我在其中混合了Concurrent::Async模块,并编写了一个名为“work”的方法来发送HTTP请求:defindexop1_result=FirstAsyncWorker.new.async.

  7. ruby - 将全局 $stdout 重新分配给控制台 - ruby - 2

    我正在尝试将$stdout设置为临时写入一个文件,然后返回到一个文件。test.rb:old_stdout=$stdout$stdout.reopen("mytestfile.out",'w+')puts"thisgoesinmytestfile"$stdout=old_stdoutputs"thisshouldbeontheconsole"$stdout.reopen("mytestfile1.out",'w+')puts"thisgoesinmytestfile1:"$stdout=old_stdoutputs"thisshouldbebackontheconsole"这是输出。r

  8. ruby - 为什么不能使用类IO的实例方法noecho? - 2

    print"Enteryourpassword:"pass=STDIN.noecho(&:gets)puts"Yourpasswordis#{pass}!"输出:Enteryourpassword:input.rb:2:in`':undefinedmethod`noecho'for#>(NoMethodError) 最佳答案 一开始require'io/console'后来的Ruby1.9.3 关于ruby-为什么不能使用类IO的实例方法noecho?,我们在StackOverflow上

  9. ruby - 如何跳过 CSV 文件的第一行并将第二行作为标题 - 2

    有没有办法跳过CSV文件的第一行,让第二行作为标题?我有一个CSV文件,第一行是日期,第二行是标题,所以我需要能够在遍历它时跳过第一行。我尝试使用slice但它会将CSV转换为数组,我真的很想将其读取为CSV,以便我可以利用header。 最佳答案 根据您的数据,您可以使用另一种方法和skip_lines-option此示例跳过所有以#开头的行require'csv'CSV.parse(DATA.read,:col_sep=>';',:headers=>true,:skip_lines=>/^#/#Markcomments!)do|

  10. ruby - 拆分字符串并分配给不同的变量 - 2

    我从ui中得到日期范围为-approved_between"=>"2013-03-17-2013-03-18"我需要拆分此approved_start_date="2013-03-17"和approved_end_date="2013-03-18"...我希望使用它在mysql中查询,因为mysql中的日期格式是created_at:2012-07-2810:35:01.我正在做的是:approved=approved_between.split("")approved_start_date=approved[0]approved_end_date=approved[2]很确定这不是处

随机推荐