我想在我的应用中实现“卡片”,例如Safari标签或App Store搜索。
我将在屏幕中央向用户显示一张卡片,在左侧和右侧显示上一张和下一张卡片的一部分。 (例如,请参阅App Store搜索或Safari选项卡)
我决定使用UICollectionView
,我需要更改页面大小(没找到方法)或实现自己的布局子类(不知道怎么做)?
请帮忙吗?
答案 0 :(得分:27)
以下是我发现获得此效果的最简单方法。它涉及您的集合视图和额外的秘密滚动视图。
设置您的收藏视图
设置集合视图的contentInset
:
_collectionView.contentInset = UIEdgeInsetsMake(0, (self.view.frame.size.width-pageSize)/2, 0, (self.view.frame.size.width-pageSize)/2);
这有助于正确抵消细胞。
设置您的秘密卷轴视图
hidden
。contentSize
设置为集合视图的预期内容大小。移动手势识别器
将秘密scrollview的手势识别器添加到集合视图,并禁用集合视图的手势识别器:
[_collectionView addGestureRecognizer:_secretScrollView.panGestureRecognizer];
_collectionView.panGestureRecognizer.enabled = NO;
<强>代表强>
- (void) scrollViewDidScroll:(UIScrollView *)scrollView {
CGPoint contentOffset = scrollView.contentOffset;
contentOffset.x = contentOffset.x - _collectionView.contentInset.left;
_collectionView.contentOffset = contentOffset;
}
当滚动视图移动时,获取其偏移量并将其设置为集合视图的偏移量。
我在此处发布了相关内容,请点击此链接了解更新:http://khanlou.com/2013/04/paging-a-overflowing-collection-view/
答案 1 :(得分:6)
您可以将UICollectionViewFlowLayout子类化并覆盖如下:
- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)contentOffset
withScrollingVelocity:(CGPoint)velocity
{
NSArray* layoutAttributesArray =
[self layoutAttributesForElementsInRect:self.collectionView.bounds];
if(layoutAttributesArray.count == 0)
return contentOffset;
UICollectionViewLayoutAttributes* candidate =
layoutAttributesArray.firstObject;
for (UICollectionViewLayoutAttributes* layoutAttributes in layoutAttributesArray)
{
if (layoutAttributes.representedElementCategory != UICollectionElementCategoryCell)
continue;
if((velocity.x > 0.0 && layoutAttributes.center.x > candidate.center.x) ||
(velocity.x <= 0.0 && layoutAttributes.center.x < candidate.center.x))
candidate = layoutAttributes;
}
return CGPointMake(candidate.center.x - self.collectionView.bounds.size.width * 0.5f, contentOffset.y);
}
这将根据速度获得下一个或上一个单元格...但它不会在当前单元格上捕捉。
答案 2 :(得分:2)
@Mike M's answer ......
class CenteringFlowLayout: UICollectionViewFlowLayout {
override func targetContentOffsetForProposedContentOffset(proposedContentOffset: CGPoint, withScrollingVelocity velocity: CGPoint) -> CGPoint {
guard let collectionView = collectionView,
let layoutAttributesArray = layoutAttributesForElementsInRect(collectionView.bounds),
var candidate = layoutAttributesArray.first else { return proposedContentOffset }
layoutAttributesArray.filter({$0.representedElementCategory == .Cell }).forEach { layoutAttributes in
if (velocity.x > 0 && layoutAttributes.center.x > candidate.center.x) ||
(velocity.x <= 0 && layoutAttributes.center.x < candidate.center.x) {
candidate = layoutAttributes
}
}
return CGPoint(x: candidate.center.x - collectionView.bounds.width / 2, y: proposedContentOffset.y)
}
}
答案 3 :(得分:1)
对Soroush的回答进行了一些编辑,这对我来说很有用。 我做的唯一编辑,而不是禁用手势:
[_collectionView addGestureRecognizer:_secretScrollView.panGestureRecognizer];
_collectionView.panGestureRecognizer.enabled = NO;
我在集合视图上禁用了滚动:
_collectionView.scrollEnabled = NO;
禁用手势也会禁用秘密的scrollview手势。
答案 4 :(得分:0)
我会添加另一种解决方案。适当的捕捉并不完美(不如设置启用分页时效果好,但效果还不错)。
我尝试过实施Soroush的解决方案,但它对我不起作用。
由于UICollectionView
是UIScrollView
的子类,因此它会响应一个重要的UIScrollViewDelegate
方法:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
targetContentOffset
(输入指针)可让您重新定义集合视图的停止点(如果您水平滑动,则为x
。)
快速说明下面的几个变量:
self.cellWidth
- 这是您的集合视图单元格的宽度(如果需要,您甚至可以在那里进行硬编码)
self.minimumLineSpacing
- 这是您在单元格之间设置的最小行间距
self.scrollingObjects
是集合视图中包含的对象数组(我需要这个主要用于计数,知道何时停止滚动)
因此,我们的想法是在集合视图的委托中实现此方法,如下所示:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
{
if (self.currentIndex == 0 && velocity.x < 0) {
// we have reached the first user and we're trying to go back
return;
}
if (self.currentIndex == (self.scrollingObjects.count - 1) && velocity.x > 0) {
// we have reached the last user and we're trying to go forward
return;
}
if (velocity.x < 0) {
// swiping from left to right (going left; going back)
self.currentIndex--;
} else {
// swiping from right to left (going right; going forward)
self.currentIndex++;
}
float xPositionToStop = 0;
if (self.currentIndex == 0) {
// first row
xPositionToStop = 0;
} else {
// one of the next ones
xPositionToStop = self.currentIndex * self.cellWidth + (self.currentIndex + 1) * self.minimumLineSpacing - ((scrollView.bounds.size.width - 2*self.minimumLineSpacing - self.cellWidth)/2);
}
targetContentOffset->x = xPositionToStop;
NSLog(@"Point of stopping: %@", NSStringFromCGPoint(*targetContentOffset));
}
期待您可能获得的任何反馈,这使得捕捉更好。我还会继续寻找更好的解决方案......
答案 5 :(得分:-6)
前一个很复杂,UICollectionView是UIScrollView的子类,所以只需这样做:
[self.collectionView setPagingEnabled:YES];
你们都准备好了。
请参阅此detailed tutorial。