adi*_*dit 50 iphone objective-c ipad ios uicollectionview
我有一个流式布局的UICollectionView,每个单元格都是一个正方形.如何确定每行上每个单元格之间的间距?我似乎找不到适合的设置.我看到nib文件中有一个min间距属性用于集合视图,但我将其设置为0并且单元格甚至没有粘贴.

还有其他想法吗?
Chr*_*ner 71
更新:这个答案的Swift版本:https://github.com/fanpyi/UICollectionViewLeftAlignedLayout-Swift
以@ matt为首,我修改了他的代码,以确保项目始终保持对齐.我发现如果一个项目本身就在一条线上,它将以流布局为中心.我做了以下更改来解决此问题.
如果您的单元格宽度不同,则可能会出现这种情况,这可能会导致如下所示的布局.由于行为的原因,最后一行始终保持对齐UICollectionViewFlowLayout,问题在于任何行中的项目,而不是最后一行.
我看到@ matt的代码.

在那个例子中,我们看到细胞如果它们自己最终在线上就会居中.下面的代码可确保您的集合视图看起来像这样.

#import "CWDLeftAlignedCollectionViewFlowLayout.h"
const NSInteger kMaxCellSpacing = 9;
@implementation CWDLeftAlignedCollectionViewFlowLayout
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray* attributesToReturn = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes* attributes in attributesToReturn) {
if (nil == attributes.representedElementKind) {
NSIndexPath* indexPath = attributes.indexPath;
attributes.frame = [self layoutAttributesForItemAtIndexPath:indexPath].frame;
}
}
return attributesToReturn;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* currentItemAttributes =
[super layoutAttributesForItemAtIndexPath:indexPath];
UIEdgeInsets sectionInset = [(UICollectionViewFlowLayout *)self.collectionView.collectionViewLayout sectionInset];
if (indexPath.item == 0) { // first item of section
CGRect frame = currentItemAttributes.frame;
frame.origin.x = sectionInset.left; // first item of the section should always be left aligned
currentItemAttributes.frame = frame;
return currentItemAttributes;
}
NSIndexPath* previousIndexPath = [NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section];
CGRect previousFrame = [self layoutAttributesForItemAtIndexPath:previousIndexPath].frame;
CGFloat previousFrameRightPoint = previousFrame.origin.x + previousFrame.size.width + kMaxCellSpacing;
CGRect currentFrame = currentItemAttributes.frame;
CGRect strecthedCurrentFrame = CGRectMake(0,
currentFrame.origin.y,
self.collectionView.frame.size.width,
currentFrame.size.height);
if (!CGRectIntersectsRect(previousFrame, strecthedCurrentFrame)) { // if current item is the first item on the line
// the approach here is to take the current frame, left align it to the edge of the view
// then stretch it the width of the collection view, if it intersects with the previous frame then that means it
// is on the same line, otherwise it is on it's own new line
CGRect frame = currentItemAttributes.frame;
frame.origin.x = sectionInset.left; // first item on the line should always be left aligned
currentItemAttributes.frame = frame;
return currentItemAttributes;
}
CGRect frame = currentItemAttributes.frame;
frame.origin.x = previousFrameRightPoint;
currentItemAttributes.frame = frame;
return currentItemAttributes;
}
@end
Run Code Online (Sandbox Code Playgroud)
mat*_*att 32
要获得最大的interitem间距,请继承UICollectionViewFlowLayout并覆盖layoutAttributesForElementsInRect:和layoutAttributesForItemAtIndexPath:.
例如,一个常见的问题是:集合视图的行是左右对齐的,除了左对齐的最后一行.假设我们希望所有的线都是左对齐的,所以它们之间的空间就是10点.这是一种简单的方法(在您的UICollectionViewFlowLayout子类中):
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect {
NSArray* arr = [super layoutAttributesForElementsInRect:rect];
for (UICollectionViewLayoutAttributes* atts in arr) {
if (nil == atts.representedElementKind) {
NSIndexPath* ip = atts.indexPath;
atts.frame = [self layoutAttributesForItemAtIndexPath:ip].frame;
}
}
return arr;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewLayoutAttributes* atts =
[super layoutAttributesForItemAtIndexPath:indexPath];
if (indexPath.item == 0) // degenerate case 1, first item of section
return atts;
NSIndexPath* ipPrev =
[NSIndexPath indexPathForItem:indexPath.item-1 inSection:indexPath.section];
CGRect fPrev = [self layoutAttributesForItemAtIndexPath:ipPrev].frame;
CGFloat rightPrev = fPrev.origin.x + fPrev.size.width + 10;
if (atts.frame.origin.x <= rightPrev) // degenerate case 2, first item of line
return atts;
CGRect f = atts.frame;
f.origin.x = rightPrev;
atts.frame = f;
return atts;
}
Run Code Online (Sandbox Code Playgroud)
这很容易的原因是我们并没有真正完成布局的繁重工作; 我们正在利用UICollectionViewFlowLayout已经为我们完成的布局工作.它已经决定了每行中有多少项; 如果你明白我的意思,我们只是阅读那些线条并将物品推到一起.
Cal*_*leb 16
有几点需要考虑:
尝试更改IB中的最小间距,但将光标留在该字段中.请注意,Xcode不会立即将文档标记为已更改.但是,当您单击其他字段时,Xcode会注意到文档已更改并在文件导航器中将其标记.因此,请务必在进行更改后选项卡或单击其他字段.
进行更改后保存storyboard/xib文件,并确保重建应用程序.不难错过这一步,然后你会不知道为什么你的改变似乎没有任何影响.
UICollectionViewFlowLayout有一个minimumInteritemSpacing属性,这是你在IB中设置的.但是集合的委托也可以有一种方法来确定项目间距.该方法特朗普是布局的属性,因此如果您在委托中实现它,则不会使用布局的属性.
请记住,那里的间距是最小间距.布局将使用该数字(无论是来自属性还是来自委托方法)作为最小允许空间,但如果线上有剩余空间,则可以使用更大的空间.因此,例如,如果将最小间距设置为0,则可能仍会在项目之间看到一些像素.如果您想要更精确地控制项目的间距,您应该使用不同的布局(可能是您自己创建的一个).
小智 5
一点数学知识就更容易解决这个问题。Chris Wagner 编写的代码非常糟糕,因为它调用了前面每个项目的布局属性。所以你滚动得越多,速度就越慢......
只需使用这样的模(我也使用我的minimumInteritemSpacing值作为最大值):
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes* currentItemAttributes = [super layoutAttributesForItemAtIndexPath:indexPath];
NSInteger numberOfItemsPerLine = floor([self collectionViewContentSize].width / [self itemSize].width);
if (indexPath.item % numberOfItemsPerLine != 0)
{
NSInteger cellIndexInLine = (indexPath.item % numberOfItemsPerLine);
CGRect itemFrame = [currentItemAttributes frame];
itemFrame.origin.x = ([self itemSize].width * cellIndexInLine) + ([self minimumInteritemSpacing] * cellIndexInLine);
currentItemAttributes.frame = itemFrame;
}
return currentItemAttributes;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
46264 次 |
| 最近记录: |