UICollectionView:分页如Safari标签或App Store,搜索(UICollec

2019-08-21 04:36发布

我想在我的应用程序如Safari标签或App Store,搜索实行“卡”。

我会在左侧和右侧屏幕的前面和后面的卡部的中央显示用户一卡。 (参见例如App Store中搜索或Safari标签)

我决定使用UICollectionView ,我需要改变页面大小(怎么没发现),或实现自己的布局子类(不知道如何)?

任何帮助,请?

Answer 1:

下面是我发现得到这种效果的最简单方式。 它涉及您的收藏视图和一个额外的秘密滚动视图。

设置您的收藏意见

  • 设置您的收藏视图及其所有数据源的方法。
  • 帧集合视图; 它应该跨越,你想成为可见的整个宽度。
  • 将集合视图的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/



Answer 2:

你也可以继承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);
}

这将让根据车速下一个或前一个单元格...它不会对当前单元格对齐不过。



Answer 3:

@Mike M的答案斯威夫特...

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)
    }

}


Answer 4:

在索罗什回答一个小编辑,这并获得成功对我来说。 唯一的编辑我做的,而不是禁用的手势:

[_collectionView addGestureRecognizer:_secretScrollView.panGestureRecognizer];
_collectionView.panGestureRecognizer.enabled = NO;

我禁用滚动上的CollectionView:

_collectionView.scrollEnabled = NO;

由于禁用禁用秘密滚动型手势以及手势。



Answer 5:

我会添加另一种解决方案。 到位的捕捉是不完美的(而不是当分页启用设置为好,但效果还不错)。

我曾尝试推行索罗什的解决方案,但它并没有为我工作。

因为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));
}

期待您的任何反馈,使得在捕捉更好的地方。 我还会继续寻找一个更好的解决办法?



Answer 6:

以前是相当复杂的,UICollectionView是的UIScrollView的子类,所以只是这样做:

[self.collectionView setPagingEnabled:YES];

你们都准备好去。

看到这个详细的教程 。



文章来源: UICollectionView: paging like Safari tabs or App Store search