web-dev-qa-db-ja.com

UICollectionView-水平スクロール、水平レイアウト?

アイコンのグリッドをレイアウトするUIScrollViewがあります。 iOS Springboardのレイアウトを想像するなら、ほぼ間違いなく正しいでしょう。水平のページスクロール(Springboardと同様)があります。ただし、レイアウトが正しくないようです。アイテムを上から下に配置しているように見えます。その結果、表示されるアイテムの数により、最後の列には2行しかありません。 Springboardで見られるように、最後のページの最後の行には2つのアイテムがあります。

UICollectionViewおよびその関連クラスを使用してこれをどのように実現できますか?カスタムUICollectionViewFlowLayoutを記述する必要がありますか?

55
Shadowman

第一のアプローチ

UIPageViewControllerの配列でUICollectionViewControllersを使用するのはどうですか?各UICollectionViewControllerで適切な数のアイテムを取得する必要がありますが、難しくはないはずです。 Springboardとまったく同じ外観になります。

第二のアプローチ

私はこれについて考えました、そして私の意見ではあなたは設定しなければなりません:

self.collectionView.pagingEnabled = YES;

UICollectionViewLayoutをサブクラス化して、独自のコレクションビューレイアウトを作成します。カスタムレイアウトオブジェクトからself.collectionViewにアクセスできるため、コレクションビューのframenumberOfSections、およびnumberOfItemsInSection:のサイズがわかります。その情報を使用して、セルのframesprepareLayout内)およびcollectionViewContentSizeを計算できます。カスタムレイアウトの作成に関する記事を次に示します。

第三のアプローチ

カスタムレイアウトを作成せずに、これ(またはその近似)を実行できます。空白のビューにUIScrollViewを追加し、ページングを有効に設定します。スクロールビューで、コレクションビューを追加します。次に、幅の制約を追加し、持っているアイテムの数をコードでチェックして、constantを正しい値に設定します。 (self.view.frame.size.width * numOfScreens)。外観は次のとおりです(セル上の数字はindexPath.rowを示します): https://www.dropbox.com/s/ss4jdbvr511azxz/collection_view.mov 方法に満足できない場合セルが順序付けられている場合、1または2を使用する必要があると思います。

67
Arek Holko

UICollectionViewFlowLayoutのスクロール方向を水平に設定しようとしましたか?

[yourFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];

スプリングボードのようにページングする場合は、次のようにコレクションビューでページングを有効にする必要があります。

[yourCollectionView setPagingEnabled:YES];
91
Erik Hunter

以下のスクリーンショットに示すように、UICollectionViewの高さをセル/アイテムの高さに減らし、「Scroll Direction」から「Horizontal」を選択する必要があります。次に、データソース実装で返されたnumberOfItemsに応じて水平にスクロールします。

enter image description here

34
Deepak Thakur

コードでUICollectionViewFlowLayoutを定義している場合、Interface Builderの設定がオーバーライドされます。したがって、scrollDirectionを再定義する必要があります。

let layout = UICollectionViewFlowLayout()
...
layout.scrollDirection = .Horizontal
self.awesomeCollectionView.collectionViewLayout = layout
12
DazChong

楽しみのために、ページングと水平スクロールセットをそのままにして、配列項目の順序を「上から下、左から右」からvisuallyに変換するメソッドを追加する方法を追加する方法もあります「左から右、上から下」を選択し、中間のセルを空の非表示セルで埋めて、間隔を右にします。 9グリッドの7つのアイテムの場合、これは次のようになります。

[1][4][7]
[2][5][ ]
[3][6][ ]

になるはずです

[1][2][3]
[4][5][6]
[7][ ][ ]

1 = 1、2 = 4、3 = 7など、6 =空です。行と列の合計数を計算してそれらを並べ替え、次に各セルの行と列の数を計算し、列の行を変更し、その逆を行うと、新しいインデックスが作成されます。セルに画像に対応する値がない場合は、空のセルを返し、cell.hidden = YES;を設定できます。

私が作成したサウンドボードアプリでは非常にうまく機能するので、もし誰かが作業中のコードを使いたい場合は追加します。このトリックを機能させるために必要なコードはごくわずかです。

更新

私はこれが最善の解決策であるとは思いませんが、リクエストにより、ここに動作するコードがあります:

- (void)viewDidLoad {
    // Fill an `NSArray` with items in normal order
    items = [NSMutableArray arrayWithObjects:
             [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 1", @"label", @"Some value 1", @"value", nil],
             [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 2", @"label", @"Some value 2", @"value", nil],
             [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 3", @"label", @"Some value 3", @"value", nil],
             [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 4", @"label", @"Some value 4", @"value", nil],
             [NSDictionary dictionaryWithObjectsAndKeys:@"Some label 5", @"label", @"Some value 5", @"value", nil],
              nil
              ];

    // Calculate number of rows and columns based on width and height of the `UICollectionView` and individual cells (you might have to add margins to the equation based on your setup!)
    CGFloat w = myCollectionView.frame.size.width;
    CGFloat h = myCollectionView.frame.size.height;
    rows = floor(h / cellHeight);
    columns = floor(w / cellWidth);
}

// Calculate number of sections
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
    return ceil((float)items.count / (float)(rows * columns));
}

// Every section has to have every cell filled, as we need to add empty cells as well to correct the spacing
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
    return rows*columns;
}

// And now the most important one
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
    UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier@"myIdentifier" forIndexPath:indexPath];

    // Convert rows and columns
    int row = indexPath.row % rows;
    int col = floor(indexPath.row / rows);
    // Calculate the new index in the `NSArray`
    int newIndex = ((int)indexPath.section * rows * columns) + col + row * columns;

    // If the newIndex is within the range of the items array we show the cell, if not we hide it
    if(newIndex < items.count) {
        NSDictionary *item = [items objectAtIndex:newIndex];
        cell.label.text = [item objectForKey:@"label"];
        cell.hidden = NO;
    } else {
        cell.hidden = YES;
    }

    return cell;
}

didSelectItemAtIndexPathメソッドを使用する場合は、cellForItemAtIndexPathで使用されているものと同じ変換を使用して、対応するアイテムを取得する必要があります。セルの余白がある場合は、それらを行と列の計算に追加する必要があります。これを機能させるには、それらが正しい必要があるためです。

8
Tum

このコードはSwift 3.1およびXcode 8.3.2でうまく機能します

override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()

        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        self.collectionView.collectionViewLayout = layout
        self.collectionView!.contentInset = UIEdgeInsets(top: -10, left: 0, bottom:0, right: 0)

        if let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout {
            layout.minimumInteritemSpacing = 0
            layout.minimumLineSpacing = 0
            layout.itemSize = CGSize(width: self.view.frame.size.width-40, height: self.collectionView.frame.size.height-10)
            layout.invalidateLayout()
        }

    }
7

@Erik Hunterから、make horizo​​ntal UICollectionViewの完全なコードを投稿します

UICollectionViewFlowLayout *collectionViewFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[collectionViewFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
self.myCollectionView.collectionViewLayout = collectionViewFlowLayout;

スイフトで

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .Horizontal
self.myCollectionView.collectionViewLayout = layout

Swift 3.0で

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
self.myCollectionView.collectionViewLayout = layout

この助けを願っています

6
Phan Van Linh

私はXcode 6.2に取り組んでおり、水平スクロールのために、属性インスペクターでスクロール方向を変更しました。

collectionView-> attribute inspector-> scroll Direction-> change to horizo​​ntalをクリックします

enter image description here 私はそれが誰かを助けることを願っています。

UICollectionViewを使用して同じSpringboardの動作を実行できます。そのためには、カスタムレイアウトのコードを記述する必要があります。

"SMCollectionViewFillLayout"を使用して、カスタムレイアウトクラスの実装で実現しました。

コードリポジトリ:

https://github.com/smindia1988/SMCollectionViewFillLayout

以下のように出力します:

1.png

First.png

2_Code_H-Scroll_V-Fill.png

enter image description here

3_Output_H-Scroll_V-Fill.pngenter image description here

4_Code_H-Scroll_H-Fill.pngenter image description here

5_Output_H-Scroll_H-Fill.pngenter image description here

6

xcode 8ではこれを行いましたが、うまくいきました:

6
Gulz

これを達成するためにカスタムUICollectionViewレイアウトを書くことができます。これが私の実装のデモ画像です:

demo image

コードリポジトリは次のとおりです。 KSTCollectionViewPageHorizo​​ntalLayout

@iPhoneDev(これも役立つかもしれません)

1
Zeng