UICollectionView does not scroll at the bottom of the first few elements

I am trying to create a chat interface that I can reuse. I'm almost done with the implementation, but there is something that bothers me about this. If I start loading messages, for example, in gif, when I first load the interface, you will see that after the 4th message there are 3 messages that do not scroll to the bottom. With the eighth - the first, which finally scrolls. It depends on the size of the screen. On the iPhone 6s testing device, it reaches the 9th message, which scrolls.

I use content insertion as a method to keep the collection visible in the following order: every time the UIToolbar below changes

toolBar.inputAccessoryViewFrameChanged = {(rect: CGRect) in Void()
    let navigationAndStatusHeight = self.navigationController != nil && self.navigationController!.navigationBar.isTranslucent ? self.navigationController!.navigationBar.frame.size.height + UIApplication.shared.statusBarFrame.height : 0
    self.collectionView.contentInset = UIEdgeInsets(top: navigationAndStatusHeight + 8, left: 8, bottom: UIScreen.main.bounds.height - rect.origin.y + 8, right: 8)
    self.collectionView.scrollIndicatorInsets.bottom = UIScreen.main.bounds.height - rect.origin.y
}

This code is run every time a new message is inserted:

func insertNewMessage(){
    self.collectionView.performBatchUpdates({
        self.collectionView.insertItems(at: [NSIndexPath(item: self.numberOfMessages() - 1, section: 0) as IndexPath])
        }) { (Bool) in
        self.scrollToBottom(animated: true)
    }
}

scrollToBottom:

func scrollToBottom(animated: Bool){
    guard self.numberOfMessages() > 0 else{
        return
    }
    self.collectionView.scrollToItem(at: IndexPath(item: self.numberOfMessages() - 1, section: 0), at: UICollectionViewScrollPosition.top , animated: animated)  
}

XCode 8.1 beta (8T29o) iOS 10.1 (14B55c)

+4
1

, , scrollToItem .

func scrollToBottomAnimated(animated: Bool) {
        guard self.collectionView.numberOfSections > 0 else{
            return
        }

        let items = self.collectionView.numberOfItems(inSection: 0)
        if items == 0 { return }

        let collectionViewContentHeight = self.collectionView.collectionViewLayout.collectionViewContentSize.height
        let isContentTooSmall: Bool = (collectionViewContentHeight < self.collectionView.bounds.size.height)

        if isContentTooSmall {
            self.collectionView.scrollRectToVisible(CGRect(x: 0, y: collectionViewContentHeight - 1, width: 1, height: 1), animated: animated)
            return
        }

        self.collectionView.scrollToItem(at: NSIndexPath(item: items - 1, section: 0) as IndexPath, at: .bottom, animated: animated)

    }
+4

Source: https://habr.com/ru/post/1658291/


All Articles