【SwiftUI】DisclosureGroup、OutlineGroup

今回はiOS14からのUI部品で利用できるようになったDisclosureGroup、OutlineGroupとについて取り上げます。

1.DisclosureGroupについて

・特徴

コンテンツを折りたためるビューです。

・コード

画面での表示が見やすいようにSpacer()を入れてます。
struct ContentView: View {
struct ToggleStates {
var oneIsOn: Bool = false
var twoIsOn: Bool = true
}
@State private var toggleStates = ToggleStates()
@State private var topExpanded: Bool = true
var body: some View {
VStack(alignment: .leading, spacing: 10.0){
DisclosureGroup("Items", isExpanded: $topExpanded) {
HStack{
Spacer().frame(width: 20.0)
Toggle("Toggle 1", isOn: $toggleStates.oneIsOn)
Spacer()
}
HStack{
Spacer().frame(width: 20.0)
Toggle("Toggle 2", isOn: $toggleStates.twoIsOn)
Spacer()
}
DisclosureGroup("Sub-items") {
HStack{
Spacer().frame(width: 20.0)
Text("Sub-item 1")
Spacer()
}
}
}
}.padding(.all, 10.0)
}
}

・画面表示

・全部閉じる
・全部開く
・Sub-itemsだけ開く

2.OutlineGroup

・特徴

階層化データ構造を表示するのに便利です。ForEach、ネストされたビューを表示するために使用されます。

・コード

区切り線を消したい場合は、「 .listStyle(SidebarListStyle()) 」を指定すると区切り線が消えます。
import SwiftUI
struct ContentView: View {
var body: some View {
List{
OutlineGroup(data, children: \.children) { item in
Text("\(item.description)")
}
}
// }.listStyle(SidebarListStyle()) //区切り線消す場合
}
}
struct FileItem: Hashable, Identifiable, CustomStringConvertible {
var id: Self { self }
var name: String
var children: [FileItem]? = nil
var description: String {
switch children {
case nil:
return "📄 \(name)"
case .some(let children):
return children.isEmpty ? "📂 \(name)" : "📁 \(name)"
}
}
}
let data =
FileItem(name: "users", children:
[FileItem(name: "user1234", children:
[FileItem(name: "Photos", children:
[FileItem(name: "photo001.jpg"),
FileItem(name: "photo002.jpg")]),
FileItem(name: "Movies", children:
[FileItem(name: "movie001.mp4")]),
FileItem(name: "Documents", children: [])
]),
FileItem(name: "newuser", children:
[FileItem(name: "Documents", children: [])
])
])

・表示

別手法:階層データについての表示方法

OutlineGroupを利用せずにListの階層表現を使う方法がありました。SmallDeskSoftwareさんが紹介されております。以下のコードはSmallDeskSoftwareさんのコードを引用させて頂いております。
・SmallDeskSoftwareさんのサイト

・コード

import SwiftUI
//
struct ContentView: View {
var body: some View {
List(data, children: \.children) { item in
OutlineItemView(item: item)
}
.padding()
}
}
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)")
}
}
}
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)"
}
}
}
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)]

・表示


このブログの人気の投稿

アプリアイコンの素材探し

【SwiftUI】グラスモーフィズムを試してみました

【SwiftUI】LazyVGridについて