8

背景

我正在实现UICollectionView(第一次)以实现分页的水平滚动视图。我希望每个图块都显示在框架的中心,其姐妹图块在左右部分可见(类似于 Safari 应用程序中的页面选择器)。我有兴趣使用UICollectionView来利用内置的单元出列,并且宁愿不使用旋转的UITableView.

问题

我发现的问题是,使用pagingEnabled = YESand时clipsToBounds = NO,一旦分页完成,就会UICollectionView删除框架外的单元格collectionView(它们不在数组中)。visibleCells任何人都可以提供有关如何在保持此基本设置的同时实现显示姐妹图块预览效果​​的建议吗?还是我错误地接近这个?

截图

开始 开始 滚动 滚动 结束 结尾

滚动屏幕是完全正确的。但是在开始和结束的镜头中,我希望在蓝色边缘有绿色可见。

这是我的 AppDelegate.m 中的内容(这里的基本设置归功于tutsplus.com ):

#import "AppDelegate.h"

@interface ViewController : UICollectionViewController
@end

@implementation ViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"ID"];
    [self.view setBackgroundColor:[UIColor blueColor]];
    // pad the collection view by 20 px
    UIEdgeInsets padding = UIEdgeInsetsMake(20.0, 20.0, 20.0, 20.0);
    [self.collectionView setFrame:UIEdgeInsetsInsetRect(self.view.frame, padding)];
    // set pagingEnabled and clipsToBounds off
    [self.collectionView setPagingEnabled:YES];
    [self.collectionView setClipsToBounds:NO];
}

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return 5;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"ID" forIndexPath:indexPath];
    UILabel *label = [[UILabel alloc] initWithFrame:cell.bounds];
    label.textAlignment = NSTextAlignmentCenter;
    label.text = [NSString stringWithFormat:@"%d", indexPath.row];
    [label setBackgroundColor:[UIColor greenColor]];
    [cell.contentView addSubview:label];
    return cell;
}
@end

@implementation AppDelegate
{
    ViewController *vc;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // setup the UICollectionViewFlowLayout
    UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
    layout.itemSize = CGSizeMake(280, 280);
    layout.minimumInteritemSpacing = 0;
    layout.minimumLineSpacing = 0;
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    // add a custom UICollectionViewController to the window
    vc = [[ViewController alloc] initWithCollectionViewLayout:layout];
    self.window.rootViewController = vc;
    self.window.backgroundColor = [UIColor yellowColor];
    [self.window makeKeyAndVisible];
    return YES;
}
@end
4

4 回答 4

10

事实证明,这个问题的解决方案实际上非常简单。我只需要将UICollectionViewCell单元格重叠足够的像素,以便在分页滚动完成后它们仍然显示在 collectionView 的框架内。相关代码是

layout.itemSize = CGSizeMake(300, 300);
layout.minimumLineSpacing = -20.0;

我继承了该方法UICollectionViewFlowLayout并覆盖了该(CGSize)collectionViewContentSize方法以返回单元格的非重叠大小。

于 2013-01-24T16:12:12.703 回答
2

非常感谢关于使用负 minimumLineSpacing 的提示。我创建了一个测试器应用程序,它使用从 xib 文件加载的集合视图单元格。单元格具有透明背景和单元格内容的“内部”视图。

这样,就不需要自定义流程布局。

https://github.com/j4johnfox/CollectionViewTester

于 2014-05-08T18:50:54.483 回答
0

我不是 collectionView 方面的专家,但它可能与 cellForItemAtIndexPath 中的这一行有关:

[cell.contentView addSubview:label];

每次调用时,都会将另一个标签子视图添加到单元格中。检查现有标签或子类 UICollectionViewCell?

于 2013-01-23T17:33:50.730 回答
0

您还需要覆盖-pointInside:withEvent:以允许滚动手势在集合视图的框架之外开始。我使用UIEdgeInsets我的集合视图子类中的属性来执行此操作:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    CGRect extendedBounds = UIEdgeInsetsInsetRect(self.bounds, self.touchAreaInsets);

    return CGRectContainsPoint(extendedBounds, point);
}

如果您不需要 App Store 安全,您可以覆盖_visibleBounds以避免负间距黑客:

- (CGRect)_visibleBounds {
     return UIEdgeInsetsInsetRect(self.bounds, self.touchAreaInsets);
}

如果您不太关注代码大小并且需要 App Store 安全性,您还可以将PSTCollectionView子类化并可能覆盖visibleBoundRects以获得相同的效果。

于 2014-07-22T20:20:16.893 回答