11

在 App Store 中显示搜索结果时,我试图模仿 Apple 的内容。(参考:http ://searchengineland.com/apple-app-search-shows-only-one-result-at-a-time-133818 )

它像卡片中的详细应用程序信息一样显示,并且是分页的。当中间有一张活动卡片并且滚动视图的分页行为仍然完好无损时,我被困在如何制作上一张和下一张卡片。

我尝试使用 UICollectionView 并将 clipSubviews 设置为 NO,希望它会显示上一页和下一页,但是一旦单元格离开屏幕,单元格就会被隐藏(从视图层次结构中删除)而不是显示。我认为这就是 UICollectionView 的享元模式(UICollectionView 的行为)。关于什么是可能的任何想法?

干杯,

伦迪·普拉纳塔

4

2 回答 2

7

问题:作为 UIScrollView 的子类的 UICollectionView 基本上以 bounds.size 的步幅对其边界进行动画处理。尽管这可能意味着您所要做的就是在保持框架更大的同时减小边界,但不幸的是 UICollectionView 不会呈现超出其当前边界的任何单元格...破坏您的预览效果。

解决方案:

  1. 创建一个 UICollectionView,将分页设置为 NO 并使用所需的帧。
  2. 创建小于 UICollectionView 的框架/边界的 UICollectionViewCells。在这个阶段,下一个单元格的一部分应该显示在框架中。在执行以下其他步骤之前,这应该是可见的。
  3. 添加一个 collectionView.contentInset.left 和 right (我假设你的布局是水平的)等于 contentOffsetValue 方法(为简单起见如下所示),以便将第一个和最后一个单元格对齐到中间。
  4. 创建一个 UICollectionViewFlowLayout 覆盖提供停止点的方法,如下所示:

像这样:

-(CGFloat)contentOffsetValue
{
    return self.collectionView.bounds.size.width * 0.5f - self.itemSize.width * 0.5f;
}

- (CGPoint)targetContentOffsetForProposedContentOffset:(CGPoint)proposedContentOffset withScrollingVelocity:(CGPoint)velocity
{

    static float EscapeVelocity = 0.5f; // otherwise snap back to the middle
    NSArray* layoutAttributesArray = [self layoutAttributesForElementsInRect:self.collectionView.bounds];

    if(layoutAttributesArray.count == 0)
        return proposedContentOffset;

    CGFloat currentBoundsCenterX = self.collectionView.contentOffset.x + self.collectionView.bounds.size.width * 0.5f;


    UICollectionViewLayoutAttributes* candidateNextLayoutAttributes = layoutAttributesArray.firstObject;


    for (UICollectionViewLayoutAttributes* layoutAttributes in layoutAttributesArray)
    {
        if ((layoutAttributes.representedElementCategory != UICollectionElementCategoryCell) ||
            (layoutAttributes == candidateNextLayoutAttributes)) // skip the first comparison
            continue;

        if(velocity.x > EscapeVelocity || velocity.x < -(EscapeVelocity))
        {
            if(velocity.x > EscapeVelocity && layoutAttributes.center.x > candidateNextLayoutAttributes.center.x)
            {

                candidateNextLayoutAttributes = layoutAttributes;
            }

            else if (velocity.x < -(EscapeVelocity) && layoutAttributes.center.x < candidateNextLayoutAttributes.center.x)
            {

                candidateNextLayoutAttributes = layoutAttributes;
            }
        }
        else
        {
            if(fabsf(currentBoundsCenterX - layoutAttributes.center.x) < fabsf(currentBoundsCenterX - candidateNextLayoutAttributes.center.x))
            {

                candidateNextLayoutAttributes = layoutAttributes;
            }
        }   
    }
    return CGPointMake(candidateNextLayoutAttributes.center.x - self.collectionView.bounds.size.width * 0.5f, proposedContentOffset.y);

}
于 2014-03-20T18:20:54.083 回答
0

我只是整理了一个示例项目,展示了如何做到这一点。我创建了一个比屏幕的 320 点宽 100 点的容器视图。然后我将 UICollectionView 放入该容器中。这会使屏幕两侧的所有内容偏移 50 个点。

然后是一个内容单元格,它只有一个背景和一个标签,因此您可以直观地识别正在发生的事情。在左侧和右侧有空单元格。在 viewDidLoad 方法中,内容插入在左右两侧设置为负值,以使空单元格现在滚动到视图中。您可以根据自己的喜好调整插图。

这非常接近地模仿了这种行为。要获得下面的标签,就像在示例中一样,您可以简单地检查 contentOffset 值以确定哪个单元格处于焦点。为此,您将使用 UICollectionView 的一部分的 UIScrollViewDelegate。

https://github.com/brennanMKE/Interfaces/tree/master/ListView

您会注意到这个示例项目有 2 个集合视图。一种是正常的水平流布局,而另一种具有较大单元格的是模仿您提到的示例的那种。

于 2013-08-02T17:56:30.203 回答