使用流布局固定 UICollectionView 中项目之间的间距 [英] Fixed spacing between item in UICollectionView with flow layout
问题描述
所以,我正在尝试使用 UICollectionView 实现一个标签列表.我正在关注本教程:,实际上由 UICollectionView 决定实际的项目间距.
但我真正想要实现的是这样的:
有什么想法吗?
我已将 Milo 的解决方案转换为 Swift:https://github.com/Coeur/UICollectionViewLeftAlignedLayout/
它只是对 UICollectionViewFlowLayout
进行子类化.
导入 UIKit/*** 简单的 UICollectionViewFlowLayout 将单元格向左对齐而不是对齐它们** 基于 https://stackoverflow.com/questions/13017257/how-do-you-determine-spacing-between-cells-in-uicollectionview-flowlayout*/打开类 UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout {打开覆盖 func layoutAttributesForElements(in rect: CGRect) ->[UICollectionViewLayoutAttributes]?{return super.layoutAttributesForElements(in: rect)?.map { $0.representedElementKind == nil ?layoutAttributesForItem(at: $0.indexPath)!: $0 }}打开覆盖 func layoutAttributesForItem(at indexPath: IndexPath) ->UICollectionViewLayoutAttributes?{守卫让 currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as?UICollectionViewLayoutAttributes,让 collectionView = self.collectionView else {//不应该发生返回零}让 sectionInset =evaluateSectionInsetForSection(at: indexPath.section)守卫 indexPath.item != 0 else {currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset)返回 currentItemAttributes}guard let previousFrame = layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame else {//不应该发生返回零}//如果当前帧,一旦左对齐到左边并拉伸到完整的集合视图//宽度与前一帧相交,然后它们在同一条线上守卫previousFrame.intersects(CGRect(x:sectionInset.left,y:currentItemAttributes.frame.origin.y,宽度:collectionView.frame.width - sectionInset.left - sectionInset.right,高度:currentItemAttributes.frame.size.height))别的 {//确保一行中的第一项左对齐currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset)返回 currentItemAttributes}currentItemAttributes.frame.origin.x = previousFrame.origin.x + previousFrame.size.width +evaluateMinimumInteritemSpacingForSection(at: indexPath.section)返回 currentItemAttributes}func评估MinimumInteritemSpacingForSection(在部分:NSInteger)->CGFloat {return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, minimumInteritemSpacingForSectionAt: section) ??最小项间间距}函数评估部分InsetForSection(在索引处:NSInteger)->UIEdgeInsets {return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, insetForSectionAt: index) ??部分插入}}扩展 UICollectionViewLayoutAttributes {func leftAlignFrame(withSectionInset sectionInset: UIEdgeInsets) {frame.origin.x = sectionInset.left}}
So, I'm trying to implement a tag list with UICollectionView. I'm following this tutorial: http://www.cocoanetics.com/2013/08/variable-sized-items-in-uicollectionview/
The issue is flow layout in UICollectionView tries to space items on the same row evenly.
As a developer, I can only specify minimumInteritemSpacingForSectionAtIndex, it's really up to the UICollectionView to determine the actual item spacing.
But what I really want to achieve is like this:
Any ideas?
I've converted Milo's solution to Swift: https://github.com/Coeur/UICollectionViewLeftAlignedLayout/
It simply subclasses UICollectionViewFlowLayout
.
import UIKit
/**
* Simple UICollectionViewFlowLayout that aligns the cells to the left rather than justify them
*
* Based on https://stackoverflow.com/questions/13017257/how-do-you-determine-spacing-between-cells-in-uicollectionview-flowlayout
*/
open class UICollectionViewLeftAlignedLayout: UICollectionViewFlowLayout {
open override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return super.layoutAttributesForElements(in: rect)?.map { $0.representedElementKind == nil ? layoutAttributesForItem(at: $0.indexPath)! : $0 }
}
open override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? {
guard let currentItemAttributes = super.layoutAttributesForItem(at: indexPath)?.copy() as? UICollectionViewLayoutAttributes,
let collectionView = self.collectionView else {
// should never happen
return nil
}
let sectionInset = evaluatedSectionInsetForSection(at: indexPath.section)
guard indexPath.item != 0 else {
currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset)
return currentItemAttributes
}
guard let previousFrame = layoutAttributesForItem(at: IndexPath(item: indexPath.item - 1, section: indexPath.section))?.frame else {
// should never happen
return nil
}
// if the current frame, once left aligned to the left and stretched to the full collection view
// width intersects the previous frame then they are on the same line
guard previousFrame.intersects(CGRect(x: sectionInset.left, y: currentItemAttributes.frame.origin.y, width: collectionView.frame.width - sectionInset.left - sectionInset.right, height: currentItemAttributes.frame.size.height)) else {
// make sure the first item on a line is left aligned
currentItemAttributes.leftAlignFrame(withSectionInset: sectionInset)
return currentItemAttributes
}
currentItemAttributes.frame.origin.x = previousFrame.origin.x + previousFrame.size.width + evaluatedMinimumInteritemSpacingForSection(at: indexPath.section)
return currentItemAttributes
}
func evaluatedMinimumInteritemSpacingForSection(at section: NSInteger) -> CGFloat {
return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, minimumInteritemSpacingForSectionAt: section) ?? minimumInteritemSpacing
}
func evaluatedSectionInsetForSection(at index: NSInteger) -> UIEdgeInsets {
return (collectionView?.delegate as? UICollectionViewDelegateFlowLayout)?.collectionView?(collectionView!, layout: self, insetForSectionAt: index) ?? sectionInset
}
}
extension UICollectionViewLayoutAttributes {
func leftAlignFrame(withSectionInset sectionInset: UIEdgeInsets) {
frame.origin.x = sectionInset.left
}
}
这篇关于使用流布局固定 UICollectionView 中项目之间的间距的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!