我想在我的应用程序中实现“卡片”,例如 Safari 选项卡或 App Store 搜索。
我将在屏幕中心向用户显示一张卡片,并在左右两侧显示上一张和下一张卡片的一部分。(例如,请参阅 App Store 搜索或 Safari 选项卡)
我决定使用UICollectionView
,我需要更改页面大小(没有找到如何)或实现自己的布局子类(不知道如何)?
请问有什么帮助吗?
我想在我的应用程序中实现“卡片”,例如 Safari 选项卡或 App Store 搜索。
我将在屏幕中心向用户显示一张卡片,并在左右两侧显示上一张和下一张卡片的一部分。(例如,请参阅 App Store 搜索或 Safari 选项卡)
我决定使用UICollectionView
,我需要更改页面大小(没有找到如何)或实现自己的布局子类(不知道如何)?
请问有什么帮助吗?
下面是我发现获得这种效果的最简单方法。它涉及您的收藏视图和一个额外的秘密滚动视图。
设置您的收藏视图
设置集合视图的contentInset
:
_collectionView.contentInset = UIEdgeInsetsMake(0, (self.view.frame.size.width-pageSize)/2, 0, (self.view.frame.size.width-pageSize)/2);
这有助于正确偏移单元格。
设置你的秘密滚动视图
hidden
如果您愿意,可以将其设置为。contentSize
为集合视图的预期内容大小。移动手势识别器
将秘密滚动视图的手势识别器添加到集合视图中,并禁用集合视图的手势识别器:
[_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/
您可以继承 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);
}
这将根据速度获得下一个或上一个单元格......但是它不会捕捉到当前单元格。
@Mike M在 Swift 中的回答……</p>
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)
}
}
对 Soroush 的回答进行了一点编辑,这对我有用。我所做的唯一编辑而不是禁用手势:
[_collectionView addGestureRecognizer:_secretScrollView.panGestureRecognizer];
_collectionView.panGestureRecognizer.enabled = NO;
我禁用了collectionview上的滚动:
_collectionView.scrollEnabled = NO;
由于禁用手势也禁用了秘密滚动视图手势。
我将添加另一个解决方案。就地捕捉并不完美(不如设置启用分页时那么好,但效果很好)。
我已经尝试实施 Soroush 的解决方案,但它对我不起作用。
因为它UICollectionView
是它的子类,UIScrollView
所以它会响应一个重要的UIScrollViewDelegate
方法,即:
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView
withVelocity:(CGPoint)velocity
targetContentOffset:(inout CGPoint *)targetContentOffset
(targetContentOffset
一个inout 指针)让您重新定义集合视图的停止点(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));
}
期待您提供的任何反馈,这些反馈可以使卡扣效果更好。我也会继续寻找更好的解决方案...
前面比较复杂,UICollectionView 是 UIScrollView 的子类,那么就这样做吧:</p>
[self.collectionView setPagingEnabled:YES];
你们都准备好了。
请参阅此详细教程。