当键盘完成改变大小和所有子视图定位时检测



在我的自定义键盘中,我在updateConstraints中添加了一个约束,增加了键盘的高度。这将导致子视图调整(也使用自动布局)到新的大小。我需要调用一个函数,当布局已经完成调整其大小和所有的子视图已经定位(存储一些新元素的位置,稍后使用,并手动更新一些元素响应这个新的布局)。当大小发生变化和元素重新定位时,例如在旋转设备后,需要再次触发此代码。我应该用什么函数来运行这些代码?

viewDidAppear只被调用一次,而且那太早了,因为那时键盘还没有调整大小。

updateViewConstraints不起作用,因为子视图还没有响应更新的约束而被布局。我试着调用self.view.setNeedsLayout()然后self.view.layoutIfNeeded(),试图在调用我的函数之前强制更新发生,但这并没有什么不同-它仍然在键盘完成布局子视图之前运行函数。

我尝试了viewDidLayoutSubviews,虽然它在视图解决后被调用,但问题是这个函数在键盘上滚动集合视图时被调用一百万次。我不能在滚动时调用这个函数,我只能在键盘大小改变并且视图已经确定位置后调用它一次。

我想过在延迟后在viewDidAppear中调用它,然后在另一个延迟后也在旋转方法(如viewWillTransitionToSize)中调用它,但这将非常脆弱。我可以增加延迟以使其不那么脆弱,但我希望确保尽早调用此方法,以确保所有内容都能尽快更新。

根据我在ios 8.3之前处理这个问题的经验,没有解决这个问题的灵丹妙药。我不知道你的具体需求是什么,但这里有一些我尝试过的可能的解决方案,也许它们会对你有帮助:

;假设你的键盘最终会被更新到你"想要"的大小,并在viewDidLayoutSubviews中执行你的布局。你为大小做一次布局,然后永远不要再做一次,除非你检测到你改变了方向。这有以下缺点:a)在你的高度限制更新之前,你的键盘只会部分出现在屏幕上,b)在某些情况下,高度限制不会得到尊重,你会留下一个畸形的键盘(你可以用计时器解决这个问题,但正如你所观察到的,它很脆弱),c)在iPhone 6/6+上的"缩放视网膜"应用程序中很难使其正常工作。

第二;检测UIInputView的高度何时发生了变化,并将该信息传递给您的集合视图,因此只有在发生这种情况时才会进行布局。根据我的经验,这种情况可能只会发生两次以上。

第三;检测何时collectionview正在滚动(您可以注册scrollview的回调),并且不要在此发生时进行昂贵的布局操作。这也是非常脆弱的。

无论你做什么,一定要测试当你在为视网膜缩放的应用程序中,当用户在有状态的布局操作发生时输入密码字段时,如果用户在你做事情时关闭键盘会发生什么,如果用户关闭键盘并在你的键盘UI被回收之前重新打开它会发生什么(当它滑动动画而不是弹出时,通常),等等。如果你不小心的话,你可能会得到一个无效的状态,这将破坏未来的操作,或者一个引用循环和/或从你的计时器对你的键盘UI的强引用。

在存储元素位置的情况下,我不知道你在做什么,但是直接读取这些属性可能比存储它们更好。国家越多,潜在的问题就越多。

最后的评论——我自己没有测试过,但是有些人报告说第三方键盘的自动布局真的很慢——你似乎在暗示你用它来布局视图——我会分析一下,看看是否真的是你的代码导致了你的问题,我认为你的键盘弹出的时间太长了。

最新更新