如何使收藏视图倒置?
Posted
技术标签:
【中文标题】如何使收藏视图倒置?【英文标题】:How to make the collection view upside down? 【发布时间】:2018-05-10 09:37:13 【问题描述】:我正在为我的一个应用程序使用具有垂直滚动方向的 Collection 视图。在这里,我想让我的 Collection 视图在不使用任何 CGAffine 变换的情况下倒置显示。是否可以借助 Flow Layout 的帮助?
我喜欢使用集合视图来实现聊天
提前致谢
【问题讨论】:
让我知道为什么它被否决了? 您能描述一下您的目标是什么吗?备注:我不是一个downvoter :) 请说明您进行了哪些研究、您已经尝试过、代码示例等。阅读How to Ask 和minimal reproducible example 并更新您的问题。 【参考方案1】:class ChatCollectionViewFlowLayout: UICollectionViewFlowLayout
private var topMostVisibleItem = Int.max
private var bottomMostVisibleItem = -Int.max
private var offset: CGFloat = 0.0
private var visibleAttributes: [UICollectionViewLayoutAttributes]?
private var isInsertingItemsToTop = false
private var isInsertingItemsToBottom = false
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]?
// Reset each time all values to recalculate them
// ════════════════════════════════════════════════════════════
// Get layout attributes of all items
visibleAttributes = super.layoutAttributesForElements(in: rect)
// Erase offset
offset = 0.0
// Reset inserting flags
isInsertingItemsToTop = false
isInsertingItemsToBottom = false
return visibleAttributes
override func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem])
// Check where new items get inserted
// ════════════════════════════════════════════════════════════
// Get collection view and layout attributes as non-optional object
guard let collectionView = self.collectionView else return
guard let visibleAttributes = self.visibleAttributes else return
// Find top and bottom most visible item
// ────────────────────────────────────────────────────────────
bottomMostVisibleItem = -Int.max
topMostVisibleItem = Int.max
let container = CGRect(x: collectionView.contentOffset.x,
y: collectionView.contentOffset.y,
width: collectionView.frame.size.width,
height: (collectionView.frame.size.height - (collectionView.contentInset.top + collectionView.contentInset.bottom)))
for attributes in visibleAttributes
// Check if cell frame is inside container frame
if attributes.frame.intersects(container)
let item = attributes.indexPath.item
if item < topMostVisibleItem topMostVisibleItem = item
if item > bottomMostVisibleItem bottomMostVisibleItem = item
// Call super after first calculations
super.prepare(forCollectionViewUpdates: updateItems)
// Calculate offset of inserting items
// ────────────────────────────────────────────────────────────
var willInsertItemsToTop = false
var willInsertItemsToBottom = false
// Iterate over all new items and add their height if they go inserted
for updateItem in updateItems
switch updateItem.updateAction
case .insert:
if topMostVisibleItem + updateItems.count > updateItem.indexPathAfterUpdate!.item
if let newAttributes = self.layoutAttributesForItem(at: updateItem.indexPathAfterUpdate!)
offset += (newAttributes.size.height + self.minimumLineSpacing)
willInsertItemsToTop = true
else if bottomMostVisibleItem <= updateItem.indexPathAfterUpdate!.item
if let newAttributes = self.layoutAttributesForItem(at: updateItem.indexPathAfterUpdate!)
offset += (newAttributes.size.height + self.minimumLineSpacing)
willInsertItemsToBottom = true
case.delete:
// TODO: Handle removal of items
break
default:
break
// Pass on information if items need more than one screen
// ────────────────────────────────────────────────────────────
// Just continue if one flag is set
if willInsertItemsToTop || willInsertItemsToBottom
// Get heights without top and bottom
let collectionViewContentHeight = collectionView.contentSize.height
let collectionViewFrameHeight = collectionView.frame.size.height - (collectionView.contentInset.top + collectionView.contentInset.bottom)
// Continue only if the new content is higher then the frame
// If it is not the case the collection view can display all cells on one screen
if collectionViewContentHeight + offset > collectionViewFrameHeight
if willInsertItemsToTop
CATransaction.begin()
CATransaction.setDisableActions(true)
isInsertingItemsToTop = true
else if willInsertItemsToBottom
isInsertingItemsToBottom = true
override func finalizeCollectionViewUpdates()
// Set final content offset with animation or not
// ════════════════════════════════════════════════════════════
// Get collection view as non-optional object
guard let collectionView = self.collectionView else return
if isInsertingItemsToTop
// Calculate new content offset
let newContentOffset = CGPoint(x: collectionView.contentOffset.x,
y: collectionView.contentOffset.y + offset)
// Set new content offset without animation
collectionView.contentOffset = newContentOffset
// Commit/end transaction
CATransaction.commit()
else if isInsertingItemsToBottom
// Calculate new content offset
// Always scroll to bottom
let newContentOffset = CGPoint(x: collectionView.contentOffset.x,
y: collectionView.contentSize.height + offset - collectionView.frame.size.height + collectionView.contentInset.bottom)
// Set new content offset with animation
collectionView.setContentOffset(newContentOffset, animated: true)
也请检查一下,它可能会将收藏视图设置为像倒置的聊天行为 https://gist.github.com/jochenschoellig/04ffb26d38ae305fa81aeb711d043068
【讨论】:
如果可能的话,您可以发送示例以了解如何使用。以上是关于如何使收藏视图倒置?的主要内容,如果未能解决你的问题,请参考以下文章