UIKit の UICollectionView を SwiftUI でもやってみようと思ったところ、どうもそれらしき代替品が見つかりませんでした(2020/04/29現在)。※Xcode12&iOS14から LazyHGrid と LazyVGrid で実現できるようになりました。詳しくはこちらの記事をどうぞ!
List や HStack・VStack などを使ってそれっぽいものを作れないかなあ〜、とあれこれやっていたところ、
既にオープンソースで公開されているものがあるではないですか!
https://github.com/Q-Mobile/QGrid
ここは意地を張らずに、先人の知恵をお借りしよう!
と言うことで今回は『QGrid』について紹介します。
SwiftUIでCollectionViewを表示する方法【QGrid】
QGrid は GitHub で公開されているオープンソースパッケージです。Xcode のプロジェクトを作成しても、最初から使うことは出来ません。プロジェクトで import するには、Swift Package Manager を使ってダウンロードしてくる必要があります。
Swift Package Manager を使ったパッケージの導入手順については、下記の記事で紹介していますので、まだ使ったことがない方はまず手順に沿って QGrid をXcodeプロジェクトに追加してください。
QGrid を Swift Package に追加出来たら、早速、QGrid を使用するソースコード上で import しましょう。
import QGrid
続いて、イニシャライザーについて確認します。イニシャライザーは2種類あります。
QGrid(data: _, columns: Int, content: (_.Element) -> _)
QGrid(data: _, columns: Int, columnsInLandscape: Int?, vSpacing: CGFloat, hSpacing: CGFloat, vPadding: CGFloat, hPadding: CGFloat, isScrollable: Bool, showScrollIndicators: Bool, content: (_.Element) -> _)
- data: _ 任意の型のデータ配列を渡します
- columns: Int 横(列)の数を指定します
- columnsInLandscape: Int? 端末を横向きにした時の横(列)の数を指定します
- vSpacing: CGFloat 縦(行)の表示間隔を指定します
- hSpacing: CGFloat 横(列)の表示間隔を指定します
- vPadding: CGFloat QGrid 全体の上下の余白を指定します
- hPadding: CGFloat QGrid 全体の左右の余白を指定します
- isScrollable: Bool スクロールさせるかどうか指定します
- showScrollIndicators: Bool スクロールバー(インディケータ)の表示・非表示を指定します
- content: (.Element) -> セルとなるコンテンツ(View)を指定します。
それでは、冒頭画像のソースコードを確認していきます。
Cat構造体
まずはデータ型の定義です。Identifiable に準拠しておく必要があります。
struct Cat: Identifiable {
let id: Int
let imageName: String
let title: String
}
GridCell
セルのViewを定義します。
今回は画像(Image)とタイトル(Text)の組み合わせで、Cat構造体のデータを持たせています。
struct GridCell: View {
let cat: Cat
var body: some View {
VStack {
Image(self.cat.imageName)
.resizable()
.frame(width: 100, height: 100)
.scaledToFit()
.clipShape(Circle())
VStack {
Spacer()
Text(self.cat.title)
.font(.caption)
.multilineTextAlignment(.center)
Spacer()
}
}
}
}
ContentView(QGrid)
最後は、実際に QGrid を使っている ContentView の内容です。
今回はテストのため Cat を静的なデータとして直接持たせていますが、通常はViewModel等で管理しておくと良いでしょう。
struct ContentView: View {
let cats: [Cat] = [
Cat(id: 1, imageName: "cat_img_scottish-fold", title: "スコティッシュフォールド"),
Cat(id: 2, imageName: "cat_img_munchkin", title: "マンチカン"),
Cat(id: 3, imageName: "cat_img_norwegian-forest-cat", title: "ノルウェージャンフォレストキャット"),
Cat(id: 4, imageName: "cat_img_mainecoon", title: "メインクーン"),
Cat(id: 5, imageName: "cat_img_bengal", title: "ベンガル"),
Cat(id: 6, imageName: "cat_img_british-shorthair", title: "ブリティッシュショートヘア"),
Cat(id: 7, imageName: "cat_img_ragdoll", title: "ラグドール"),
Cat(id: 8, imageName: "cat_img_exotic-shorthair", title: "エキゾチックショートヘア"),
Cat(id: 9, imageName: "cat_img_minuet", title: "ミヌエット"),
Cat(id: 10, imageName: "cat_img_american-shorthair", title: "アメリカンショートヘア")
]
var body: some View {
QGrid(self.cats,
columns: 3,
columnsInLandscape: 5,
vSpacing: 16,
hSpacing: 8,
vPadding: 16,
hPadding: 16,
isScrollable: true,
showScrollIndicators: false
) { cat in
GridCell(cat: cat)
}
}
}
縦向きの場合、列数は3つ、横向きになると5つの表示になります。
また、上下左右の余白に 16pt を設け、列間隔を 8pt 、行間隔を 16pt としています。
以上で QGrid の使い方を紹介しました。
iOS非公式のオープンソースではありますが、取り急ぎ SwiftUI で CollectionView を実現するには利用しない手はありません。
とは言え、UICollectionView のようにiOS公式のレイアウト要素としてリリースして貰いたいものですね。
おわり
コメントを残す