我有一个UICollectionView
,直到我开始滚动,其工作正常。 这里是一些图片第一:
正如你可以看到它的伟大。 当我开始滚动(启用分页)第一个进入了一下屏幕外:
这就是问题。 渊源我认为有3次,我想滚动,只显示3次。 但是,因为它滚动(启用分页),它隐藏了第一种观点的一点点,展现从下一页的下一个第一种观点的一点。
这里是一个视频,因为它是有点难以解释: 问题的视频(Dropbox的)
这里是我的照片UICollectionView
设置:
这将是巨大的,如果有人能帮助!
Answer 1:
最根本的问题是流式布局并非设计用于支持分页。 为了实现分页效果,你将不得不牺牲细胞之间的空间。 并仔细计算单元框架,使其能够通过集合视图帧没有余数来划分。 我会解释原因。
话说以下布局正是你想要的。
请注意,最左边空白处(绿色)不是单元格间距的一部分。 它是由流布局部插入确定。 由于流布局不支持异构间距值。 这不是一个简单的任务。
因此,设置的间隔和插入后。 下面的布局你会得到什么。
滚动到下一个页面之后。 你的细胞显然不对齐,你所期望的。
使单元格间距0就可以解决这个问题。 但是,如果你想在页面上的额外余量,特别是如果保证金是从单元格间距不同它限制了你的设计。 它还要求视图帧必须是由所述单元框整除。 有时,如果您的视图帧不固定(考虑旋转情况)的疼痛。
真正的解决办法是继承UICollectionViewFlowLayout并覆盖下面的方法
- (CGSize)collectionViewContentSize
{
// Only support single section for now.
// Only support Horizontal scroll
NSUInteger count = [self.collectionView.dataSource collectionView:self.collectionView
numberOfItemsInSection:0];
CGSize canvasSize = self.collectionView.frame.size;
CGSize contentSize = canvasSize;
if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal)
{
NSUInteger rowCount = (canvasSize.height - self.itemSize.height) / (self.itemSize.height + self.minimumInteritemSpacing) + 1;
NSUInteger columnCount = (canvasSize.width - self.itemSize.width) / (self.itemSize.width + self.minimumLineSpacing) + 1;
NSUInteger page = ceilf((CGFloat)count / (CGFloat)(rowCount * columnCount));
contentSize.width = page * canvasSize.width;
}
return contentSize;
}
- (CGRect)frameForItemAtIndexPath:(NSIndexPath *)indexPath
{
CGSize canvasSize = self.collectionView.frame.size;
NSUInteger rowCount = (canvasSize.height - self.itemSize.height) / (self.itemSize.height + self.minimumInteritemSpacing) + 1;
NSUInteger columnCount = (canvasSize.width - self.itemSize.width) / (self.itemSize.width + self.minimumLineSpacing) + 1;
CGFloat pageMarginX = (canvasSize.width - columnCount * self.itemSize.width - (columnCount > 1 ? (columnCount - 1) * self.minimumLineSpacing : 0)) / 2.0f;
CGFloat pageMarginY = (canvasSize.height - rowCount * self.itemSize.height - (rowCount > 1 ? (rowCount - 1) * self.minimumInteritemSpacing : 0)) / 2.0f;
NSUInteger page = indexPath.row / (rowCount * columnCount);
NSUInteger remainder = indexPath.row - page * (rowCount * columnCount);
NSUInteger row = remainder / columnCount;
NSUInteger column = remainder - row * columnCount;
CGRect cellFrame = CGRectZero;
cellFrame.origin.x = pageMarginX + column * (self.itemSize.width + self.minimumLineSpacing);
cellFrame.origin.y = pageMarginY + row * (self.itemSize.height + self.minimumInteritemSpacing);
cellFrame.size.width = self.itemSize.width;
cellFrame.size.height = self.itemSize.height;
if (self.scrollDirection == UICollectionViewScrollDirectionHorizontal)
{
cellFrame.origin.x += page * canvasSize.width;
}
return cellFrame;
}
- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewLayoutAttributes * attr = [super layoutAttributesForItemAtIndexPath:indexPath];
attr.frame = [self frameForItemAtIndexPath:indexPath];
return attr;
}
- (NSArray *)layoutAttributesForElementsInRect:(CGRect)rect
{
NSArray * originAttrs = [super layoutAttributesForElementsInRect:rect];
NSMutableArray * attrs = [NSMutableArray array];
[originAttrs enumerateObjectsUsingBlock:^(UICollectionViewLayoutAttributes * attr, NSUInteger idx, BOOL *stop) {
NSIndexPath * idxPath = attr.indexPath;
CGRect itemFrame = [self frameForItemAtIndexPath:idxPath];
if (CGRectIntersectsRect(itemFrame, rect))
{
attr = [self layoutAttributesForItemAtIndexPath:idxPath];
[attrs addObject:attr];
}
}];
return attrs;
}
通知,上述代码段中只支持单节和水平滚动的方向。 但也不是很难扩大。
另外,如果你没有数百万个细胞。 缓存那些UICollectionViewLayoutAttributes可能是一个好主意。
Answer 2:
你可以在UICollectionView禁用分页并实现了自定义页面宽度/像这样的偏移的自定义水平滚动条/分页机制:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset
{
float pageWidth = 210;
float currentOffset = scrollView.contentOffset.x;
float targetOffset = targetContentOffset->x;
float newTargetOffset = 0;
if (targetOffset > currentOffset)
newTargetOffset = ceilf(currentOffset / pageWidth) * pageWidth;
else
newTargetOffset = floorf(currentOffset / pageWidth) * pageWidth;
if (newTargetOffset < 0)
newTargetOffset = 0;
else if (newTargetOffset > scrollView.contentSize.width)
newTargetOffset = scrollView.contentSize.width;
targetContentOffset->x = currentOffset;
[scrollView setContentOffset:CGPointMake(newTargetOffset, 0) animated:YES];
}
Answer 3:
这个答案是这样晚了,但我刚才一直在玩这个问题,发现漂移的原因是行间距 。 如果你想UICollectionView /的FlowLayout页的整倍数的你的细胞宽度,必须设置:
UICollectionViewFlowLayout *flowLayout = (UICollectionViewFlowLayout *)collectionView.collectionViewLayout;
flowLayout.minimumLineSpacing = 0.0;
你不会觉得行距进入在水平滚动播放,但显然它。
在我来说,我与寻呼同时从左到右,一个细胞实验,与细胞之间没有空格。 页面动辄推出漂移的一点点从期望的位置,并且它似乎线性积累。 〜每匝10.0 PTS。 我意识到10.0 minimumLineSpacing在流布局的默认值。 当我将它设置为0.0,无漂移,当我把它设置为界限宽度的一半,每个页面漂流边界的一个额外的一半。
更改minimumInteritemSpacing 没有影响 。
编辑-从文件UICollectionViewFlowLayout :
@属性(非原子)CGFloat的minimumLineSpacing;
讨论
...
对于垂直滚动网格,该值表示连续行之间的最小间距。 为水平滚动的网格,该值表示连续列之间的最小间距。 该间距不施加到集管和第一线之间或最后一行和页脚之间的空间。
此属性的默认值是10.0。
Answer 4:
从下面的文章的解决方案是优雅而简洁。 其主要思想是创造了滚动与传递所有contentOffset值你的CollectionView的顶部。
http://b2cloud.com.au/tutorial/uiscrollview-paging-size/
应该通过实施该方法来表示:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity;
像它与pagingEnabled发生我没有实现平滑的动画= YES。
Answer 5:
我知道这个问题是旧的,但任何人谁发生在此绊倒。
所有你需要做的正确的,这是设置MinimumInterItemSpacing为0,降低内容的框架。
Answer 6:
我想我明白这个问题。 我会试着让你明白这一点。
如果你仔细观察,你会看到,这个问题只发生逐渐而不是只在第一页上刷卡。
如果我理解正确的话,在你的应用程序,目前,每UICollectionView项目是那些圆形的盒子,我们看到,你有所有的人之间的一些偏移/利润是不变的。 这是什么原因造成的问题。
相反,你应该做的,是让一个UICollectionView项目是整个视图的宽度的1/3,然后添加里面圆润的图像视图。 来指代图像,绿色应该是你UICollectionViewItem,而不是黑色的。
Answer 7:
@devdavid是当场上的flowLayout.minimumLineSpacing为零。
它也可以在布局编辑器完成,线路设置最小间距为0:
Answer 8:
你滚你自己UICollectionViewFlowLayout
?
如果是这样,加入-(CGPoint) targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
将帮助您计算在滚动视图应该停止。
这可能会实现(注:UNTESTED!):
-(CGPoint) targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset
withScrollingVelocity:(CGPoint)velocity
{
CGFloat offsetAdjustment = MAXFLOAT;
CGFloat targetX = proposedContentOffset.x + self.minimumInteritemSpacing + self.sectionInset.left;
CGRect targetRect = CGRectMake(proposedContentOffset.x, 0.0, self.collectionView.bounds.size.width, self.collectionView.bounds.size.height);
NSArray *array = [super layoutAttributesForElementsInRect:targetRect];
for(UICollectionViewLayoutAttributes *layoutAttributes in array) {
if(layoutAttributes.representedElementCategory == UICollectionElementCategoryCell) {
CGFloat itemX = layoutAttributes.frame.origin.x;
if (ABS(itemX - targetX) < ABS(offsetAdjustment)) {
offsetAdjustment = itemX - targetX;
}
}
}
return CGPointMake(proposedContentOffset.x + offsetAdjustment, proposedContentOffset.y);
}
Answer 9:
我的答案是基于答案https://stackoverflow.com/a/27242179/440168但更简单。
您应该将UIScrollView
上述UICollectionView
,给他们平等的大小:
@property (nonatomic, weak) IBOutlet UICollectionView *collectionView;
@property (nonatomic, weak) IBOutlet UIScrollView *scrollView;
然后配置contentInset
集合视图,例如:
CGFloat inset = self.view.bounds.size.width*2/9;
self.collectionView.contentInset = UIEdgeInsetsMake(0, inset, 0, inset);
和contentSize
滚动视图:
self.scrollView.contentSize = CGSizeMake(self.placesCollectionView.bounds.size.width*[self.collectionView numberOfItemsInSection:0],0);
不要忘记设置滚动视图的委托:
self.scrollView.delegate = self;
并实施主要法宝:
- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
if (scrollView == self.scrollView) {
CGFloat inset = self.view.bounds.size.width*2/9;
CGFloat scale = (self.placesCollectionView.bounds.size.width-2*inset)/scrollView.bounds.size.width;
self.collectionView.contentOffset = CGPointMake(scrollView.contentOffset.x*scale - inset, 0);
}
}
Answer 10:
您UICollectionView
的宽度应在单元尺寸宽度+左,右插图的准确乘法。 在示例中,如果单元宽度为96,则UICollectionView
的宽度应为(96 + 5 + 5) * 3 = 318
。 或者,如果你想保留UICollectionView的320宽度,你的单元尺寸宽度应320 / 3 - 5 - 5 = 96.666
。
如果这没有帮助,你UICollectionView
的宽度可能比什么是在厦门国际银行文件中设置,应用程序运行时不同。 要检查这一点-添加NSLog
声明印出视图的大小在运行时:
NSLog(@"%@", NSStringFromCGRect(uiContentViewController.view.frame));
Answer 11:
这是我遇到同样的问题,我贴在另一篇文章中我的解决方案,所以我在这里再次张贴。
我发现了一个解决的办法,这涉及继承的UICollectionViewFlowLayout。
我的CollectionViewCell大小是302 X 457和设置我的最小线间距为18(9pix针对每个小区)
当您从类扩展有需要将超过缠身的一些方法。 其中之一是
- (CGSize)collectionViewContentSize
在这种方法中,我需要添加了什么是在UICollectionView总宽度。 这包括([数据源计数] * widthOfCollectionViewCell)+([数据源计数] * 18)
这里是我的自定义UICollectionViewFlowLayout方法....
-(id)init
{
if((self = [super init])){
self.itemSize = CGSizeMake(302, 457);
self.sectionInset = UIEdgeInsetsMake(10, 10, 10, 10);
self.minimumInteritemSpacing = 0.0f;
self.minimumLineSpacing = 18.0f;
[self setScrollDirection:UICollectionViewScrollDirectionHorizontal];
}
return self;
}
-(CGSize)collectionViewContentSize{
return CGSizeMake((numCellsCount * 302)+(numCellsCount * 18), 457);
}
这为我工作,所以我希望别人发现它有用!
Answer 12:
您还可以设置视图的以“320 +间距”,然后设置页面宽度能够为yes。 它会滚动“320 +空间”的每一次。 我想这是因为页面能够将滚动视图的宽度,但没有屏幕的宽度。
Answer 13:
我觉得我有这个问题的解决方案。 但我不,如果这是最好的。
UICollectionViewFlowLayout
确实含有一种叫做财产sectionInset
。 所以,你可以设置部分内陷,以任何你需要的是,让1页等于一个部分。 因此,你的滚动应该自动适应正常的网页(=部分)
Answer 14:
我曾与分页类似的问题。 即使电池插图均为0,细胞正是在宽度和高度的大小相同UICollectionView
,寻呼是不妥当的。
我注意到像一个错误的声音在这个版本( UICollectionView
,iOS 6中):我可以看到,如果我有工作UICollectionView
与宽度= 310px以上,高度= 538px,我遇到了麻烦。 但是,如果我减少宽度,比方说,300像素(高度相同),我得到的东西完美地工作!
对于一些未来的参考,我希望它能帮助!
Answer 15:
试图让水平分页对细胞的第插图和细胞及线间距为3×3格工作时,我遇到类似的问题。
对我来说,答案(尝试的许多建议后 - 包括继承UICollectionViewFlowLayout和各种UIScrollView的委托解决方案)很简单。 我只是打破我的数据集成的9个项目(或更少)的部分,并利用numberOfSectionsInCollectionView和numberOfItemsInSection UICollectionView数据源的方法使用的部分在UICollectionView。
该UICollectionView的水平分页现在精美的作品。 我推荐这种方法目前人撕扯自己的头发出过类似的情景。
Answer 16:
如果您使用的是默认流布局为您UICollectionView,不想每个单元之间的任何空间,你可以将其miniumumLineSpacing通过属性设置为0:
((UICollectionViewFlowLayout *) self.collectionView.collectionViewLayout).minimumLineSpacing = 0;
文章来源: UICollectionView align logic missing in horizontal paging scrollview