I am trying to detect if the last cell in a collectionView
is visible.
var isLastCellVisible: Bool {
let lastIndexPath = NSIndexPath(forItem: self.messages.count - 1, inSection: 0)
let visibleIndexPaths = self.collectionView.indexPathsForVisibleItems()
let lastCellPositionY = self.collectionView.layoutAttributesForItemAtIndexPath(lastIndexPath)!.frame.origin.y
let bottomInset = self.collectionView.contentInset.bottom // changes when the keyboard is shown / hidden
let contentHeight = self.collectionView.contentSize.height
if visibleIndexPaths.contains(lastIndexPath) && (contentHeight - lastCellPositionY) > bottomInset {
return true
} else {
return false
}
}
What works:
If the last cell is visible and the keyboard is shown so that the cell is not hidden by it, the above code returns true. If it is hidden it returns false.
But I can't figure out how to return true, when the user scrolls up and the last cell is above the keyboard.
lastCellPositionY
and contentHeight
don't change when the collectionView
gets scrolled up.
Instead
self.collectionView.bounds.origin.y
does change, but I don't know how to compare lastCellPositionY
to it, since they don't share the same origin and self.collectionView.bounds.origin.y
is significantly less than lastCellPositionY
.
I use this code (translated to Swift from the commits in this thread: https://github.com/jessesquires/JSQMessagesViewController/issues/1458)
var isLastCellVisible: Bool {
if self.messages.isEmpty {
return true
}
let lastIndexPath = NSIndexPath(forItem: self.messages.count - 1, inSection: 0)
var cellFrame = self.collectionView.layoutAttributesForItemAtIndexPath(lastIndexPath)!.frame
cellFrame.size.height = cellFrame.size.height
var cellRect = self.collectionView.convertRect(cellFrame, toView: self.collectionView.superview)
cellRect.origin.y = cellRect.origin.y - cellFrame.size.height - 100
// substract 100 to make the "visible" area of a cell bigger
var visibleRect = CGRectMake(
self.collectionView.bounds.origin.x,
self.collectionView.bounds.origin.y,
self.collectionView.bounds.size.width,
self.collectionView.bounds.size.height - self.collectionView.contentInset.bottom
)
visibleRect = self.collectionView.convertRect(visibleRect, toView: self.collectionView.superview)
if CGRectContainsRect(visibleRect, cellRect) {
return true
}
return false
}