UICollectionView top cells disappear while animating keyboard appearance

I have UICollectionView with cells inside. Everything works well except one thing.

During keyboard appearance animation, top cells that are about to go offscreen just disappear in place without any animation

https://drive.google.com/file/d/17GROrgdqNDMZJf-ym-0FjT6NgFQHjelc/view?usp=sharing

I have tried to implement

finalLayoutAttributesForDisappearingItem
but it has no any effect. Also tried to expand rect in
layoutAttributesForElementsInRect
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
  let rect = CGRect(x: rect.minX, y: rect.midY - 312, width: rect.width, height: rect.height + 312)
  return itemAttributesCache.filter { $0.frame.intersects(rect) }
}

but also with no luck.


The only working solution that i found is to expand

UICollectionView.frame
above the screen to the keyboard height and set
UICollectionView.contentInset.top
to the keyboard height. It works but absolutely ugly.

Any ideas how to fix it?

Yes, not very nice looking.


Why don't you scroll the superview of the collectionView ?


That's usually what I do when showing keyboard (if the field I have to type into would be hidden by keyboard).

I have the exact same problem.
Have you managed to found a solution for this?


The problem you are most likely seeing here is that you are triggering a server side animation, which don't work very well with collection views.

How exactly are you setting up your animation? Most likely the collection view prepares the target state to send it over to CoreAnimation to then animate this out of process.
I just have a reference for my collectionView bottom constraint. When I receive the keyboard appearance notification, i just set the keyboard height as a constant to my constraint as well as when I receive the keyboard dismiss notification.

The only animation I have is:

Code Block
guard let keyboardAnimationDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
UIView.animate(withDuration: keyboardAnimationDuration) { [weak self] in
self?.view.layoutIfNeeded()
}


And when the keyboard appears, the cell at top of the screen, they literally disappear and then the bottom cells whose stay above the keyboard, the definitely scroll. When the keyboard dismisses, the same happens but inverted. The cells that have scrolled, scroll back to bottom screen and the top cells just become visible (it's like the cells alpha property have been modified and animated).

Happens with all models.

This is triggering a server side animation. Basically the collection view updates its layout and the render server just animates the frame of the collection view. At this point though the collection view already has done its layout for the new frame, so it has already removed cells that are no longer visible in this new frame. That's why you are seeing cells disappearing. Keyboard dodging should generally be implemented by changing a scroll view's contentInset, not its frame.

There are two options for dodging the keyboard:
a) Use UICollectionViewController, which does this automatically for you. You shouldn't have to do anything.
b) Animate the contentInset of the collection view, which is what the view controller is doing internally as well. If you do this, also make sure to adjust the scroll indicator insets and double check that the math is correct on devices with and without a safe area inset at the bottom.
In this case I've a UIViewController hosting a collectionView that is pinned to all superview's corners.

I did as you suggested on b) but i got exactly the same behavior. The top cells literally disappearing, and on scroll down due to keyboad dismiss, the bottom cells scroll down as expected and top cells just come visible again without any scroll.

Code Block
@objc func adjustForKeyboard(notification: NSNotification) {
guard let keyboardValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue else { return }
guard let keyboardAnimationDuration = notification.userInfo?[UIResponder.keyboardAnimationDurationUserInfoKey] as? Double else { return }
let keyboardScreenEndFrame = keyboardValue.cgRectValue
let keyboardViewEndFrame = view.convert(keyboardScreenEndFrame, from: view.window)
let keyboardBeingPresented = notification.name == UIResponder.keyboardWillShowNotification
UIView.animate(withDuration: keyboardAnimationDuration) {
if keyboardBeingPresented {
self.collectionView.contentInset.bottom += keyboardViewEndFrame.height - self.view.safeAreaInsets.bottom
self.collectionView.contentOffset.y += keyboardViewEndFrame.height - self.view.safeAreaInsets.bottom
} else {
self.collectionView.contentInset.bottom -= keyboardViewEndFrame.height - self.view.safeAreaInsets.bottom
}
self.collectionView.scrollIndicatorInsets = self.collectionView.contentInset
}
}


Can you file a feedback ticket, ideally with this sample attached? I believe this should work but I'd need to check with a colleague and check this out in the debugger to see what's going on here.
Any solution for this? I'm still face this issue, it's very annoying
@ minhphamdbp 
It is difficult to follow track of this thread as several are asking questions.
Are you the author of the original post @ mikalaifromborisov ?
Did you file a bug report ?

If so, did you try scrolling the superview when keyboard appears ?
No sorry I'm not the author of this post, I just have exactly same question with the author
The superview of collection view is not scrollable so what do you mean scrolling the superview?

Frameworks Engineer guy shown me some solutions but it seems like no suitable

Hi, is it possible to solve this without using UICollectionViewController ?

I actually solve the issue by animating a layout update after changing the content insets, like @nmfp was doing, something like

 self.collectionView.contentInset = newInsets

UIView.animate(withDuration: keyboardAnimationDuration) { [weak self] in
		self?.view.layoutIfNeeded()
}
UICollectionView top cells disappear while animating keyboard appearance
 
 
Q