質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

解決済

1回答

1214閲覧

CollectionViewのカスタムレイアウトに等間隔のマージン(隙間)を作りたい。 [swift]

kou009

総合スコア16

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

0クリップ

投稿2018/05/31 00:49

[やりたいこと]
・Cell間のマージンを等間隔(サイズは2)にしたい。

CollectionViewのカスタムレイアウトを実装しています。
こちらのサイトを参考に作成しました。

Cell間のマージン(隙間)のサイズを2にしたいです。(シミュレーターで表示されてるマージンはのサイズは、8です。)
シミュレーターでは、topのマージンがなくなっていますが、topのマージンも2にしたいです。
すべてのCell間(top,left,bottom,right全て)に等間隔のマージン(サイズは2)を作りたいです。

イメージ説明

CustomCollectionViewFlowLayoutクラスを、コレクションビューにアタッチしています。
コードはこちらのページのCustomCollectionViewFlowLayoutクラスのコードとほぼ同じです。
イメージ説明

カスタムレイアウトのコードです。

swift

1 2import UIKit 3 4class CustomCollectionViewFlowLayout: UICollectionViewFlowLayout { 5 6 private static let kMaxRow = 3 7 var maxColumn = kMaxRow 8 9 private var sectionCells = [[CGRect]]() 10 private var contentSize = CGSize.zero 11 12 required init?(coder aDecoder: NSCoder) { 13 super.init(coder: aDecoder) 14 } 15 16 override init() { 17 super.init() 18 self.sectionInset = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2) 19 self.minimumLineSpacing = 2 20 self.minimumInteritemSpacing = 2 21 self.sectionInset = UIEdgeInsetsMake(2, 2, 2, 2) 22 } 23 24 override func prepare() { 25 super.prepare() 26 sectionCells = [[CGRect]]() 27 28 if let collectionView = self.collectionView { 29 contentSize = CGSize(width: collectionView.bounds.width - collectionView.contentInset.left - collectionView.contentInset.right, height: 0) 30 let smallCellSideLength: CGFloat = (contentSize.width - super.sectionInset.left - super.sectionInset.right - (super.minimumInteritemSpacing * (CGFloat(maxColumn) - 1.0))) / CGFloat(maxColumn) 31 32 for section in (0..<collectionView.numberOfSections) { 33 var cells = [CGRect]() 34 let numberOfCellsInSection = collectionView.numberOfItems(inSection: section) 35 var height = contentSize.height 36 37 var x:CGFloat = 0 38 var y:CGFloat = 0 39 var cellwidth:CGFloat = 0 40 var cellheight:CGFloat = 0 41 42 for i in (0..<numberOfCellsInSection) { 43 let position = i % (numberOfCellsInSection) 44 let cellPosition = position % 6 45 46 switch cellPosition { 47 case 0: 48 if section % 2 == 0 { 49 x = super.sectionInset.left 50 y = contentSize.height + super.sectionInset.top 51 cellwidth = 2 * smallCellSideLength + super.minimumInteritemSpacing 52 cellheight = 2 * smallCellSideLength + super.minimumLineSpacing 53 }else{ 54 x = super.sectionInset.left 55 y = contentSize.height + super.sectionInset.top 56 cellwidth = smallCellSideLength 57 cellheight = smallCellSideLength 58 } 59 case 1: 60 if section % 2 == 0 { 61 x = 2 * (smallCellSideLength + super.minimumInteritemSpacing) + super.sectionInset.left 62 y = 0 * (smallCellSideLength + super.minimumLineSpacing) + contentSize.height + super.sectionInset.top 63 cellwidth = smallCellSideLength; cellheight = smallCellSideLength 64 }else { 65 x = smallCellSideLength + super.minimumInteritemSpacing + super.sectionInset.left 66 y = (0 * (smallCellSideLength + super.minimumLineSpacing)) + contentSize.height + super.sectionInset.top 67 cellwidth = 2 * smallCellSideLength + super.minimumInteritemSpacing 68 cellheight = 2 * smallCellSideLength + super.minimumLineSpacing 69 } 70 case 2: 71 if section % 2 == 0 { 72 x = 2 * (smallCellSideLength + super.minimumInteritemSpacing) + super.sectionInset.left 73 y = 1 * (smallCellSideLength + super.minimumLineSpacing) + contentSize.height + super.sectionInset.top 74 cellwidth = smallCellSideLength; cellheight = smallCellSideLength 75 }else{ 76 x = super.sectionInset.left 77 y = (1 * (smallCellSideLength + super.minimumLineSpacing)) + contentSize.height + super.sectionInset.top 78 cellwidth = smallCellSideLength; cellheight = smallCellSideLength 79 } 80 case 3: 81 x = super.sectionInset.left 82 y = 2 * (smallCellSideLength + super.minimumLineSpacing) + contentSize.height + super.sectionInset.top 83 cellwidth = smallCellSideLength; cellheight = smallCellSideLength 84 case 4: 85 x = smallCellSideLength + super.minimumInteritemSpacing + super.sectionInset.left 86 y = 2 * (smallCellSideLength + super.minimumLineSpacing) + contentSize.height + super.sectionInset.top 87 cellwidth = smallCellSideLength; cellheight = smallCellSideLength 88 case 5: 89 x = 2 * (smallCellSideLength + super.minimumInteritemSpacing) + super.sectionInset.left 90 y = 2 * (smallCellSideLength + super.minimumLineSpacing) + contentSize.height + super.sectionInset.top 91 cellwidth = smallCellSideLength; cellheight = smallCellSideLength 92 default: 93 x = 0; y = 0 94 cellwidth = 0; cellheight = 0 95 break 96 } 97 98 let cellRect = CGRect(x: x, y: y, width: cellwidth, height: cellheight) 99 cells.append(cellRect) 100 101 if (height < cellRect.origin.y + cellRect.height) { 102 height = cellRect.origin.y + cellRect.height 103 } 104 } 105 contentSize = CGSize(width: contentSize.width, height: height) 106 sectionCells.append(cells) 107 } 108 } 109 } 110 111 override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? { 112 var layoutAttributes = [UICollectionViewLayoutAttributes]() 113 114 if let collectionView = self.collectionView { 115 for i in 0..<collectionView.numberOfSections { 116 let numberOfCellsInSection = collectionView.numberOfItems(inSection: i); 117 for j in 0..<numberOfCellsInSection { 118 119 let indexPath = IndexPath(row: j, section: i) 120 if let attributes = layoutAttributesForItem(at: indexPath) { 121 if (rect.intersects(attributes.frame)) { 122 layoutAttributes.append(attributes) 123 } 124 } 125 } 126 } 127 } 128 return layoutAttributes 129 } 130 131 override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 132 let attributes = super.layoutAttributesForItem(at: indexPath) 133 attributes?.frame = sectionCells[indexPath.section][indexPath.row] 134 return attributes 135 } 136 137 override var collectionViewContentSize : CGSize { 138 return contentSize 139 } 140} 141

CollectionViewを保持しているクラスです。

swift

1 2import UIKit 3import SDWebImage 4 5class DiscoverViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource { 6 7 @IBOutlet weak var myCollectionView: UICollectionView! 8 9 var posts: [Post] = [] 10 11 12 13 override func viewDidLoad() { 14 super.viewDidLoad() 15 16 17 myCollectionView.delegate = self 18 myCollectionView.dataSource = self 19 20 21 loadTopPosts() 22 } 23 24 func loadTopPosts() { 25 Api.Post.observeTopPosts(page: page) { (post) in 26 self.posts.append(post) 27 self.myCollectionView.reloadData() 28 } 29 } 30 31 32 33 func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { 34 return section<posts.count/6 ? 6 : posts.count%6 35 } 36 //セクションの総数を返す 37 func numberOfSections(in collectionView: UICollectionView) -> Int { 38 return (posts.count-1)/6+1 39 } 40 //Cellに値を設定する 41 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { 42 43 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath) as! CustomCollectionViewCell 44 45 46 let photoUrlString = self.posts[indexPath.section * 6 + indexPath.row].imageUrls[0] 47 let photoUrl = URL(string: photoUrlString) 48 cell.imageView1.sd_setImage(with: photoUrl) 49 50 return cell 51 } 52 53 54} 55 56

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

CollectionViewには疎いですが、
参考にしたページを見させていただきました。

その通り、コードをコピーして、走らせ、
改変して見て様子を見ました。

Swift

1 self.sectionInset = UIEdgeInsets(top: 2, left: 2, bottom: 2, right: 2) 2 self.minimumLineSpacing = 2 3 self.minimumInteritemSpacing = 2 4 self.sectionInset = UIEdgeInsetsMake(2, 2, 2, 2) 5

で、わかったことですが、
上記の1行目と4行目で同じことを別の方法で定義してるように見えます。
どちらかをコメントアウトしても、表示は何も変わらなかったです。
なので、どちらか一方で定義すれば良さそうです。
そして、それが定義しているものはセクション全体の周囲の空白です。

イメージ説明

これがself.sectionInsetを30に設定した時です。

self.minimumLineSpacing を80に設定を変えてみたら、
下記のような表示になりました。

イメージ説明

同様にself.minimumInteritemSpacing を80に変えたら
今度は下記のようになりました。

イメージ説明

最後にkou009さんの実現したいことですが、
自分は全てを2に設定したら、全ての間隔が2に設定され、
そのまま狭い間隔でした。
シュミレーターだけでなく、実機で試して見ましたか?

投稿2018/05/31 06:32

hameji

総合スコア1380

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

kou009

2018/05/31 08:40

CustomCollectionViewFlowLayoutのコードが間違ってると思いこんでいましたが、 hamejiさんが等間隔で表示できたとのことですので、 コードはそのままで他のやり方を試してみました。 そしたら、すべての間隔を2で表示させることができました。 以前のやり方は、storyboardから、collectionViewに直接CustomCollectionViewFlowLayoutをアタッチしていましたが、 アタッチせずに、動的にレイアウトを生成(myCollectionView.collectionViewLayout = CustomCollectionViewFlowLayout())したら、サイズ2で等間隔でレイアウトを作ることができました。 丁寧にご回答いただきありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問