草庐IT

ios - 当键盘可见时,UICollectionView 不会重新显示滚动到屏幕外的补充 View

coder 2023-09-23 原文

我有一个 UICollectionViewLayout 子类,它指定围绕单元格以及在一个部分的开始和结束处的补充 View 。出于这个问题的目的,我创建了一个 sample project它有我的布局子类的精简版。我还创建了 a video这直观地演示了我将要描述的问题。

示例项目是这样布置的([0, 1] = section 0 item 1):

  • [0, 0] HEYCollectionViewElementKindHeaderA
  • 类型的“节”级补充 View
  • [0, 0] HEYCollectionViewElementKindCellA
  • 类型的“项目”级补充 View
  • [0, 0] 此索引路径的单元格。
  • [0, 1] 另一个CellA变体
  • [0, 1] 此索引路径的单元格。
  • 等等

在示例项目中,我在 HEYCollectionViewLayout 类中注释掉了一些额外的标题。如果取消注释它们,您会看到更多未正确重用的 View 。

所有 header View 都有一个 UITextField 内部,尽管我能够用 UITextView 和我自己的 UIView 重现这个问题> 设置了 inputView 并成为第一响应者。当键盘在 CellA [0, 0] 元素中的文本字段上处于事件状态并且您将其上方的补充 View 滚动到屏幕外然后再返回时,这些 View 不会重新添加到 Collection View 。

在我的调查中,我发现 UICollectionReusableView 子类被放入重用队列并在 View 层次结构中显示为 hidden=YES,正如预期的那样等待重用。当键盘未激活时,我将元素重新滚动,之前显示的类的相同实例将被重新使用并显示在屏幕上。

我已经尝试让 UICollectionViewLayout 要求在每次边界更改时重新布局(通过从 -shouldInvalidateLayoutForBoundsChange: 返回 YES);这没有效果,元素最终仍然隐藏。

我无法在互联网上找到关于此问题的任何其他报告,但我已经在 Xcode 5.1.1 中的 iOS 模拟器 7.1 和运行 iOS 7.1.2 的 iPod Touch 上重现了它。


我已经用可能的解决方法更新了上面的 repo:

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (BOOL)resignFirstResponder {
    BOOL didResign = [super resignFirstResponder];

    if (didResign) {
        // This works around http://stackoverflow.com/q/25189751/551420

        dispatch_async(dispatch_get_main_queue(), ^{
            [self.collectionView performBatchUpdates:^{

            } completion:^(BOOL finished) {

            }];
        });
    }

    return didResign;
}

我认为问题是 UICollectionView 中的某种损坏的内部状态,每当 UICollectionViewController 退出第一响应者(因为 child 成为第一响应者)时,通过强制更新来解决).

这似乎不是正确的解决方案,所以我没有将其标记为答案,但如果其他人遇到问题,这就是我目前正在尝试解决的方法。

最佳答案

在我看来,这绝对是某种内部状态,用于处理出现问题的第一响应者。

我发现的一种解决方法是通过添加额外的索引使每个补充 View 的索引路径唯一:

- (void)prepareLayout {
    [super prepareLayout];

    [self.supplementaryViewAttributes removeAllObjects];
    [self.cellAttributes removeAllObjects];

    CGFloat minimumY = 0;

    for (NSInteger sectionIdx = 0; sectionIdx < self.collectionView.numberOfSections; sectionIdx++) {
        NSIndexPath *sectionIndexPath = [NSIndexPath indexPathForItem:0 inSection:sectionIdx];

        NSInteger suppViewIdx = 0;
        NSIndexPath *suppIndexPath = [sectionIndexPath indexPathByAddingIndex:suppViewIdx];
        suppViewIdx++;

        [self newAttributesForSupplementaryViewAtIndexPath:suppIndexPath
                                                      kind:HEYCollectionViewElementKindHeaderA
                                                    height:HEYCollectionViewHeaderHeight
                                                  minimumY:&minimumY];

        suppIndexPath = [sectionIndexPath indexPathByAddingIndex:suppViewIdx];
        suppViewIdx++;

        [self newAttributesForSupplementaryViewAtIndexPath:suppIndexPath
                                                      kind:HEYCollectionViewElementKindHeaderB
                                                    height:HEYCollectionViewHeaderHeight
                                                  minimumY:&minimumY];

        for (NSInteger itemIdx = 0; itemIdx < [self.collectionView numberOfItemsInSection:sectionIdx]; itemIdx++) {
            NSIndexPath *itemIndexPath = [NSIndexPath indexPathForItem:itemIdx inSection:sectionIdx];

            suppIndexPath = [itemIndexPath indexPathByAddingIndex:suppViewIdx];
            suppViewIdx++;

            [self newAttributesForSupplementaryViewAtIndexPath:suppIndexPath
                                                          kind:HEYCollectionViewElementKindCellA
                                                        height:HEYCollectionViewCellHeight
                                                      minimumY:&minimumY];

            suppIndexPath = [itemIndexPath indexPathByAddingIndex:suppViewIdx];
            suppViewIdx++;

            [self newAttributesForSupplementaryViewAtIndexPath:suppIndexPath
                                                          kind:HEYCollectionViewElementKindCellB
                                                        height:HEYCollectionViewCellHeight
                                                      minimumY:&minimumY];

            [self newAttributesForCellAtIndexPath:itemIndexPath minimumY:&minimumY];
        }
    }
}

如果这是一个内部错误,那么这对我来说似乎是一个不错的解决方法,因为它不会改变您的索引路径的 sectionitem 值,而且它还意味着您不必子类化 UICollectionView 来强制它在退出第一响应者时进行更新。

但是,如果您目前正在 compare:-ing 或测试索引路径上的相等性(例如使用 isEqual:),那么此解决方法可能会破坏它。相反,您必须确保只比较 sectionitem 以保持相同的功能。

关于ios - 当键盘可见时,UICollectionView 不会重新显示滚动到屏幕外的补充 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25189751/

有关ios - 当键盘可见时,UICollectionView 不会重新显示滚动到屏幕外的补充 View的更多相关文章

  1. ruby-on-rails - Rails - 一个 View 中的多个模型 - 2

    我需要从一个View访问多个模型。以前,我的links_controller仅用于提供以不同方式排序的链接资源。现在我想包括一个部分(我假设)显示按分数排序的顶级用户(@users=User.all.sort_by(&:score))我知道我可以将此代码插入每个链接操作并从View访问它,但这似乎不是“ruby方式”,我将需要在不久的将来访问更多模型。这可能会变得很脏,是否有针对这种情况的任何技术?注意事项:我认为我的应用程序正朝着单一格式和动态页面内容的方向发展,本质上是一个典型的网络应用程序。我知道before_filter但考虑到我希望应用程序进入的方向,这似乎很麻烦。最终从任何

  2. ruby-on-rails - 渲染另一个 Controller 的 View - 2

    我想要做的是有2个不同的Controller,client和test_client。客户端Controller已经构建,我想创建一个test_clientController,我可以使用它来玩弄客户端的UI并根据需要进行调整。我主要是想绕过我在客户端中内置的验证及其对加载数据的管理Controller的依赖。所以我希望test_clientController加载示例数据集,然后呈现客户端Controller的索引View,以便我可以调整客户端UI。就是这样。我在test_clients索引方法中试过这个:classTestClientdefindexrender:template=>

  3. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  4. ruby - 如何在续集中重新加载表模式? - 2

    鉴于我有以下迁移:Sequel.migrationdoupdoalter_table:usersdoadd_column:is_admin,:default=>falseend#SequelrunsaDESCRIBEtablestatement,whenthemodelisloaded.#Atthispoint,itdoesnotknowthatusershaveais_adminflag.#Soitfails.@user=User.find(:email=>"admin@fancy-startup.example")@user.is_admin=true@user.save!ende

  5. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  6. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  7. ruby-on-rails - 如何在我的 Rails 应用程序 View 中打印 ruby​​ 变量的内容? - 2

    我是一个Rails初学者,但我想从我的RailsView(html.haml文件)中查看Ruby变量的内容。我试图在ruby​​中打印出变量(认为它会在终端中出现),但没有得到任何结果。有什么建议吗?我知道Rails调试器,但更喜欢使用inspect来打印我的变量。 最佳答案 您可以在View中使用puts方法将信息输出到服务器控制台。您应该能够在View中的任何位置使用Haml执行以下操作:-puts@my_variable.inspect 关于ruby-on-rails-如何在我的R

  8. ruby - 在 Ruby 中用键盘诅咒数组浏览 - 2

    我正在尝试在Ruby中制作一个cli应用程序,它接受一个给定的数组,然后将其显示为一个列表,我可以使用箭头键浏览它。我觉得我已经在Ruby中看到一个库已经这样做了,但我记不起它的名字了。我正在尝试对soundcloud2000中的代码进行逆向工程做类似的事情,但他的代码与SoundcloudAPI的使用紧密耦合。我知道cursesgem,我正在考虑更抽象的东西。广告有没有人见过可以做到这一点的库或一些概念证明的Ruby代码可以做到这一点? 最佳答案 我不知道这是否是您正在寻找的,但也许您可以使用我的想法。由于我没有关于您要完成的工作

  9. ruby - 即时确定方法的可见性 - 2

    我正在编写一个方法,它将在一个类中定义一个实例方法;类似于attr_accessor:classFoocustom_method(:foo)end我通过将custom_method函数添加到Module模块并使用define_method定义方法来实现它,效果很好。但我无法弄清楚如何考虑类(class)的可见性属性。例如,在下面的类中classFoocustom_method(:foo)privatecustom_method(:bar)end第一个生成的方法(foo)必须是公共(public)的,第二个(bar)必须是私有(private)的。我怎么做?或者,如何找到调用我的cust

  10. ruby-on-rails - 如何在 Rails View 上显示错误消息? - 2

    我是rails的新手,想在form字段上应用验证。myviewsnew.html.erb.....模拟.rbclassSimulation{:in=>1..25,:message=>'Therowmustbebetween1and25'}end模拟Controller.rbclassSimulationsController我想检查模型类中row字段的整数范围,如果不在范围内则返回错误信息。我可以检查上面代码的范围,但无法返回错误消息提前致谢 最佳答案 关键是您使用的是模型表单,一种显示ActiveRecord模型实例属性的表单。c

随机推荐