【徒然iOS】気ままにUIKit36〜UICollectionViewLayout〜
概要
このマガジンは四十を過ぎたおっさんが、
を参考にStoryboardでiOSアプリを完全に趣味で楽しんでいるだけな記事を気ままに上げてます。
今回
をやる〜〜〜
前準備
念の為、バックアップ
新しいクラス
ビューコントローラの追加
イニシャルビューの変更
をいつも通りやってから本題へ💃
本題
コレクションビューレイアウトとは、
コレクションビューに表示するセルのレイアウトを
自由にカスタマイズする
ために利用されるクラス
⒈前々回のビューの続きなので、前々回の新しいビューを作る
⒉自作レイアウトのクラスを作る
⒊コレクションビューのアイデンティティインスペクタ設定項目のLayoutに「Custom」、Classに「TestCollectionViewLayout」を入力
⒋MyUICollectionViewLayoutクラスにコードを組み込む
class TestCollectionViewLayout: UICollectionViewLayout {
let numberColumns = 2 //列数
let height:CGFloat = 50 //セルの高さ
//レイアウト配列
private var layoutData = [UICollectionViewLayoutAttributes]()
//レイアウトを準備するメソッド
override func prepareLayout() {
//全体の幅
let allWidth = CGRectGetWidth(collectionView!.bounds) - collectionView!.contentInset.left - collectionView!.contentInset.right
//列の幅
let columnWidth = allWidth / CGFloat(numberColumns)
//座標
var y:CGFloat = 0
var x:CGFloat = 0
//要素数ぶんループ
for count in 0 ..< collectionView!.numberOfItemsInSection(0) {
let indexPath = NSIndexPath(forItem:count, inSection:0)
//レイアウトの配列に位置とサイズを登録する。
let frame = CGRect(x:x, y:y, width:columnWidth, height: height)
let attributes = UICollectionViewLayoutAttributes(forCellWithIndexPath: indexPath)
attributes.frame = frame
layoutData.append(attributes)
//X座標を更新
if(count % 2 == 0) {
x = columnWidth
} else {
x = 0
}
//Y座標を更新
y = y + height
}
}
//レイアウトを返すメソッド
override func layoutAttributesForElementsInRect(rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return layoutData
}
//全体サイズを返すメソッド
override func collectionViewContentSize() -> CGSize {
//全体の幅
let allWidth = CGRectGetWidth(collectionView!.bounds) - collectionView!.contentInset.left - collectionView!.contentInset.right
//全体の高さ
let allHeight = CGFloat(collectionView!.numberOfItemsInSection(0)) * height
return CGSize(width:allWidth, height:allHeight)
}
}
一旦、シミュレータ実行
なので、JumptoDefinition
を開いてSizeを検索
👉スーパークラス=適用してるプロトコル内のメソッドである可能性が高い
なので
//全体サイズを返すメソッド
override var collectionViewContentSize: CGSize {
//全体の幅
let allWidth = CGRectGetWidth(collectionView!.bounds) - collectionView!.contentInset.left - collectionView!.contentInset.right
//全体の高さ
let allHeight = CGFloat(collectionView!.numberOfItems(inSection: 0)) * height
return CGSize(width:allWidth, height:allHeight)
}
に書き方を変更して実行すると
例の如くラベルが表示されてないので、CollectionViewCellを
AutoLayoutの制約を前回までと同様に追加していく
⒌シミュレータを実行
理由は実は簡単で、、、
カスタムレイアウトで設定してる幅と高さよりも外側にラベルが配置されているから 藁
(だったら端折らずに最初から書いとけよって話なんだけど、自分の中で繋がってる操作や設計を端折って説明するからこういうサイト記事や書籍はマジで多い)
なので、
シミュレータ再実行
⒍ブラッシュアップ
は、AutoLayoutなんかもここまででやっているので前回同様、今回も割愛🙇
以上。
ここまでの操作を見ればわかると思うけど、
参照記事では、前々回の続き〜〜〜
とか言いながら、実は全然、続きではないのでは?
って感じ。
(*説明を端折りすぎるとこうなるね〜〜〜〜)
今回のコードまとめ
ViewController側
import UIKit
class CollectionLayoutViewController: UIViewController,UICollectionViewDataSource {
//データの個数を返すメソッド
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 30
}
//データを返すメソッド
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
//コレクションビューから識別子「TestCell」のセルを取得する。
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyColletionLayoutCell", for: indexPath) as! MtCollectionLayoutViewCell
//セルの背景色をランダムに設定する。
cell.backgroundColor = UIColor(
red: CGFloat(drand48()),
green: CGFloat(drand48()),
blue: CGFloat(drand48()),
alpha: 1.0
)
//セルのラベルに番号を設定する。
cell.myCollectionLayoutLabel.text = String(indexPath.row + 1)
return cell
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
CocoaTouchClass側
import UIKit
class MyUICollectionViewLayout: UICollectionViewLayout {
let numberColumns = 2 //列数
let height:CGFloat = 50 //セルの高さ
//レイアウト配列
private var layoutData = [UICollectionViewLayoutAttributes]()
//レイアウトを準備するメソッド
override func prepare() {
//全体の幅
let allWidth = CGRectGetWidth(collectionView!.bounds) - collectionView!.contentInset.left - collectionView!.contentInset.right
//列の幅
let columnWidth = allWidth / CGFloat(numberColumns)
//座標
var y:CGFloat = 0
var x:CGFloat = 0
//要素数ぶんループ
for count in 0 ..< collectionView!.numberOfItems(inSection: 0) {
let indexPath = NSIndexPath(item:count, section:0)
//レイアウトの配列に位置とサイズを登録する。
let frame = CGRect(x:x, y:y, width:columnWidth, height: height)
let attributes = UICollectionViewLayoutAttributes(forCellWith: indexPath as IndexPath)
attributes.frame = frame
layoutData.append(attributes)
//X座標を更新
if(count % 2 == 0) {
x = columnWidth
} else {
x = 0
}
//Y座標を更新
y = y + height
}
}
//レイアウトを返すメソッド
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return layoutData
}
//全体サイズを返すメソッド
override var collectionViewContentSize: CGSize {
//全体の幅
let allWidth = CGRectGetWidth(collectionView!.bounds) - collectionView!.contentInset.left - collectionView!.contentInset.right
//全体の高さ
let allHeight = CGFloat(collectionView!.numberOfItems(inSection: 0)) * height
return CGSize(width:allWidth, height:allHeight)
}
}
今回の教訓
設計を考えて、コードを組むのが基本だから、コードから見てラベルを配置する!
とか言いつつ、簡単なテクニックで、結構、柔軟に修正対応はできる。
=それがオブジェクト指向言語の旨味だったりする。
⒈コードを覚える暇があったら、
オブジェクト指向言語の旨味を最大限に活かす方法や考え方を身につける
コードを丸暗記して理解してみたいな感じで階段型でやるのがSEとかレガシー言語からエンジニア気取ってる人は多いけど、そういう人ほど、こういうサンプルコードを見たことがないから、サンプルさえ知っていて、コードの修正方法の調べ方さえわかれば簡単にできることすら、何週間も悩んでいたりする
👉それで納期ギリギリか余計な予算をクライアントが追加したら意味ないんだけどね。
⒉百のコード解析よりも、まずはひとつでも多くサンプルコードに触れる
*進化し続ける最新のプログラミング言語では特に、、、。
Apple公式
さて、次回は
コレクションビューもこれでラストだねえ〜〜〜!
明日は、祝日だから休むし、来週から平日は、短期のアルバイトを入れたから、週末に2記事ずつくらいのペースにしばらくなるかも〜〜〜〜!