Sponsor Link
アウトラインビュー
List を使って、アウトラインを表示することができるように拡張されました。
Outline() みたいなビューが用意されるかと思っていたら、なんと List でできるようになりました。
Mac の AppKit を使っていて、OutlineView と TableView を置き換えるのが面倒に思うことがあったので、設定だけで切り替えられるのは便利だと思います。
List を使います
ということで、拡張された List ビューを使います。
Apple のドキュメントは、こちら。
children: に対して、子要素を RandomAccessCollection に準拠するタイプで返すようなキーパスを与えます。
表示するときに、List ビューがこのキーパスを使用します。
なお、各要素のキーパス値が、nil であれば、下位層を表示するためのシンボルを表示しません。空の配列等が返されるのであれば、現時点では子要素がないけれども、持つかもしれないということで、下位層を表示するためのシンボルは表示されます。
難しく見えるかもしれませんが以下のように使えます。
List(data, children: \.children) { item in
// item を使ったビュー
}
階層構造を持つデータを表示できます
当たり前ですが、階層的にアクセスできるような構造を持つ要素が必要になります。
以下のような struct を作ってみました。
struct OutlineItem: Identifiable, Hashable, CustomStringConvertible {
var id: Self { self }
var name: String
enum ItemType {
case Folder
case Symbol
case Default
}
var type: ItemType = .Default
var children:[OutlineItem]? = nil
var description: String {
switch type {
case .Folder:
return "\(name) ( \(children?.count ?? 0) )"
case .Symbol:
return "\(name)"
case .Default:
return "\(name)"
}
}
}
Children に、子要素を配列として持つようにしています。
具体的には、以下のようなサンプルデータを作りました。
let data = [OutlineItem(name: "Symbols", type: .Folder, children: [
OutlineItem(name: "Transportation", type: .Folder, children: [
OutlineItem(name: "bicycle", type: .Symbol, children: nil),
OutlineItem(name: "car", type: .Symbol, children: nil)
]),
OutlineItem(name: "Empty", type: .Folder, children: []),
OutlineItem(name: "Weather", type: .Folder, children: [
OutlineItem(name: "sun.min", type: .Symbol, children: nil),
OutlineItem(name: "cloud", type: .Symbol, children: nil),
OutlineItem(name: "moon", type: .Symbol, children: nil)
])]),
OutlineItem(name: "Symbols.Fill", type: .Folder, children: [
OutlineItem(name: "clock.fill", type: .Symbol, children: nil)]),
OutlineItem(name: "sum", type: .Symbol, children: nil)]
OutlineItem が階層的に設定されています。
アウトライン表示
ビュー側では以下のように使用することになります。
struct ContentView: View {
var body: some View {
List(data, children: \.children) { item in
OutlineItemView(item: item)
}
.padding()
}
}
OutlineItem を表示するためのビューを別途作りました。
struct OutlineItemView : View {
let item: OutlineItem
var body: some View {
switch item.type {
case .Folder:
HStack {
Image(systemName: "folder")
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
Text("\(item.description)")
}
case .Symbol:
Image(systemName: item.name)
.resizable()
.scaledToFit()
.frame(width: 30, height: 30)
default:
Text("\(item.description)")
}
}
}
できあがったアウトラインビュー
インデント、アイテムの開閉 など
特に設定せずともアウトライン表示であれば、以下のような表示・動作になりました。
- 子要素が親要素よりも少し右に寄って表示される
- 子要素を持つ要素には、右側に ” > ” が表示されて、開閉することができる
まとめ: List を使うと、アウトライン表示が簡単にできます
- List ビューに children: 指定することで、アウトライン表示される
- 親子関係の表示位置調整は自動で行われる
- 開閉のシンボル表示やタップによる表示切り替えはデフォルトで実装されている
説明は以上です。
Sponsor Link