31

私はかなり長い間、この割り当てに苦労してきました。私が開発したいのは、垂直方向と水平方向の両方で連続的にスクロールするスクロールビューまたはコレクションビューです。

これは、これがどのように見えるべきかのイメージです。透明なボックスは、メモリから再ロードされるビュー/セルです。ビュー/セルが画面の外に出るとすぐに、次の新しいセルに再利用する必要がありますUITableViewController

連続スクロール

UICollectionViewaは、水平方向または垂直方向の両方ではなく、無限スクロールのみを行うことができることを知っています。ただし、を使用してこれを行う方法がわかりませんUIScrollViewこの質問の回答に添付されたコードを試してみましたが、ビューを再作成することができます (例: % 20) が、それは実際には必要なものではありません..さらに、継続的ではありません。

HBO Goアプリがこれを行うので、それが可能であることはわかっています..まったく同じ機能が必要です。

私の質問: どうすれば目標を達成できますか? 方法を教えてくれるガイド/チュートリアルはありますか? 何も見つかりません。

4

4 に答える 4

30

UIScrollView中心から一定の距離を離した後、中心を再設定する手法を使用して、無限スクロールを取得できます。まず、contentSize少しスクロールできるように十分な大きさにする必要があるため、セクション内のアイテム数の 4 倍とセクション数の 4 倍を返し、cellForItemAtIndexPathメソッドで mod 演算子を使用して正しいインデックスを取得します。私の配列。layoutSubviews次に、再センタリングを行うために のサブクラスでオーバーライドする必要がありますUICollectionView(これは、WWDC 2011 のビデオ「Advanced Scroll View Techniques」で説明されています)。サブビューとしてコレクション ビュー (IB で設定) を持つコントローラー クラスを次に示します。

#import "ViewController.h"
#import "MultpleLineLayout.h"
#import "DataCell.h"

@interface ViewController ()
@property (weak,nonatomic) IBOutlet UICollectionView *collectionView;
@property (strong,nonatomic) NSArray *theData;
@end

@implementation ViewController

- (void)viewDidLoad {
    self.theData = @[@[@"1",@"2",@"3",@"4",@"5"], @[@"6",@"7",@"8",@"9",@"10"],@[@"11",@"12",@"13",@"14",@"15"],@[@"16",@"17",@"18",@"19",@"20"]];
    MultpleLineLayout *layout = [[MultpleLineLayout alloc] init];
    self.collectionView.collectionViewLayout = layout;
    self.collectionView.showsHorizontalScrollIndicator = NO;
    self.collectionView.showsVerticalScrollIndicator = NO;
    layout.scrollDirection = UICollectionViewScrollDirectionHorizontal;
    self.view.backgroundColor = [UIColor blackColor];
    [self.collectionView registerClass:[DataCell class] forCellWithReuseIdentifier:@"DataCell"];
    [self.collectionView reloadData];
}


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

- (NSInteger)numberOfSectionsInCollectionView: (UICollectionView *)collectionView {
    return 16;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView  cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    DataCell *cell = [collectionView  dequeueReusableCellWithReuseIdentifier:@"DataCell" forIndexPath:indexPath];
    cell.label.text = self.theData[indexPath.section %4][indexPath.row %5];
    return cell;
}

- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {
   // UICollectionViewCell *item = [collectionView cellForItemAtIndexPath:indexPath];
    NSLog(@"%@",indexPath);

}

UICollectionViewFlowLayoutサブクラスは次のとおりです。

#define space 5
#import "MultpleLineLayout.h"

@implementation MultpleLineLayout { // a subclass of UICollectionViewFlowLayout
    NSInteger itemWidth;
    NSInteger itemHeight;
}

-(id)init {
    if (self = [super init]) {
        itemWidth = 60;
        itemHeight = 60;
    }
    return self;
}

-(CGSize)collectionViewContentSize {
    NSInteger xSize = [self.collectionView numberOfItemsInSection:0] * (itemWidth + space); // "space" is for spacing between cells.
    NSInteger ySize = [self.collectionView numberOfSections] * (itemHeight + space);
    return CGSizeMake(xSize, ySize);
}

- (UICollectionViewLayoutAttributes *)layoutAttributesForItemAtIndexPath:(NSIndexPath *)path {
    UICollectionViewLayoutAttributes* attributes = [UICollectionViewLayoutAttributes layoutAttributesForCellWithIndexPath:path];
    attributes.size = CGSizeMake(itemWidth,itemHeight);
    int xValue = itemWidth/2 + path.row * (itemWidth + space);
    int yValue = itemHeight + path.section * (itemHeight + space);
    attributes.center = CGPointMake(xValue, yValue);
    return attributes;
}


-(NSArray*)layoutAttributesForElementsInRect:(CGRect)rect {
    NSInteger minRow =  (rect.origin.x > 0)?  rect.origin.x/(itemWidth + space) : 0; // need to check because bounce gives negative values  for x.
    NSInteger maxRow = rect.size.width/(itemWidth + space) + minRow;
    NSMutableArray* attributes = [NSMutableArray array];
    for(NSInteger i=0 ; i < self.collectionView.numberOfSections; i++) {
        for (NSInteger j=minRow ; j < maxRow; j++) {
            NSIndexPath* indexPath = [NSIndexPath indexPathForItem:j inSection:i];
            [attributes addObject:[self layoutAttributesForItemAtIndexPath:indexPath]];
        }
    }
    return attributes;
}

最後に、 のサブクラスを次に示しますUICollectionView

-(void)layoutSubviews {
    [super layoutSubviews];
    CGPoint currentOffset = self.contentOffset;
    CGFloat contentWidth = self.contentSize.width;
    CGFloat contentHeight = self.contentSize.height;
    CGFloat centerOffsetX = (contentWidth - self.bounds.size.width)/ 2.0;
    CGFloat centerOffsetY = (contentHeight - self.bounds.size.height)/ 2.0;
    CGFloat distanceFromCenterX = fabsf(currentOffset.x - centerOffsetX);
    CGFloat distanceFromCenterY = fabsf(currentOffset.y - centerOffsetY);

    if (distanceFromCenterX > contentWidth/4.0) { // this number of 4.0 is arbitrary
        self.contentOffset = CGPointMake(centerOffsetX, currentOffset.y);
    }
    if (distanceFromCenterY > contentHeight/4.0) {
        self.contentOffset = CGPointMake(currentOffset.x, centerOffsetY);
    }
}
于 2013-03-21T17:15:33.423 に答える