Search
Duplicate

[SwiftUI] DisclosureGroup & OutlineGroup

์ƒ์„ฑ์ผ
2024/08/25 23:40
ํƒœ๊ทธ
ํ‹ˆํ‹ˆํžˆ ์ž๊ธฐ๊ฐœ๋ฐœ
SwiftUI

[SwiftUI] DisclosureGroup & OutlineGroup

SwiftUI์˜ List ์— ์†ํ•ด์žˆ๋Š” ํƒ€์ž…์ธ DisclosureGroup & OutlineGroup
ย ๋‹จ์ˆœํ•˜๊ฒŒ ์ƒ๊ฐํ•ด์„œ ์ ‘๊ณ  ํŽผ ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ์ธ ํŠธ๋ฆฌ ๊ตฌ์กฐ์˜ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ทฐ
โ€ข
์ด ๋‘ ๊ฐ€์ง€๋Š” iOS 14 ์ด์ƒ์—์„œ๋งŒ ์ œ๊ณต์„ ํ•˜๊ณ  ์žˆ๋‹ค.

DisclosureGroup

โ€ข
์ œ์–ด์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ํ•˜์œ„ ์ปจํ…์ธ ๋ฅผ ํ‘œ์‹œํ•˜๊ฑฐ๋‚˜ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ทฐ์ด๋‹ค.
struct DisclosureGroup<Label, Content> where Label: View, Content: View
Swift
๋ณต์‚ฌ
์ œ๋„ค๋ฆญํ•˜๊ฒŒ Label์„ ๋ฐ›๊ณ  ํ•˜์œ„ ๋‹ด๊ธธ Content๋ฅผ ๋ฐ›์•„ ๊ตฌ์„ฑํ•˜๋Š” ํ˜•์‹
์ฆ‰, ํ•ด๋‹น ๋ทฐ๋Š” ๋‚ด์šฉ์„ ์‹๋ณ„ํ•  ์ˆ˜ ์žˆ๋Š” Label๊ณผ ํ‘œ์‹œ ๋ฐ ์ˆจ๊น€ ์ฒ˜๋ฆฌํ•  ์ˆ˜ ์žˆ๋Š” ํ•˜์œ„ ๋ทฐ๋กœ ์ปจํŠธ๋กค ํ•œ๋‹ค.

DisclosureGroup ๊ตฌํ˜„

import SwiftUI struct DisclosureGroupView: View { @State private var expanded: Bool = false var body: some View { DisclosureGroup("1๋ฒˆ ๊ทธ๋ฃน", isExpanded: $expanded) { Text("1๋ฒˆ ๊ทธ๋ฃน์— ์†ํ•œ ํ…์ŠคํŠธ") DisclosureGroup("2๋ฒˆ ๊ทธ๋ฃน") { Text("2๋ฒˆ ๊ทธ๋ฃน์— ์†ํ•œ ํ…์ŠคํŠธ") } } } }
Swift
๋ณต์‚ฌ
์œ„์—์„œ ํŽผ์น˜๊ณ  ์ˆจ๊ธฐ๋Š” ์ƒํƒœ๋ฅผ ์ œ์–ดํ•˜๋Š” expanded ๋ณ€์ˆ˜๋ฅผ ์ƒ์„ฑ
๊ทธ๋ฆฌ๊ณ  1๋ฒˆ, ์ฆ‰, ์ตœ์ƒ์œ„์—์„œ DisclosureGroup์„ ๋งŒ๋“ค๊ณ  ์ด ๋ณ€์ˆ˜๋ฅผ ํ†ตํ•ด ๋„ฃ์–ด์ฃผ๋ฉด ์žฌ๋ถ€ ๊ตฌํ˜„์„ ํ†ตํ•ด ์ด ๊ฐ’์„ ์‚ฌ์šฉ์ž์˜ ์•ก์…˜์— ๋”ฐ๋ผ ๋ฐ”๊ฟ”์ค€๋‹ค.
์ฆ‰, isExpanded ํŒŒ๋ผ๋ฏธํ„ฐ๋Š” Binding<Bool> ํƒ€์ž…์ธ ๊ฒƒ.
public init(_ titleKey: LocalizedStringKey, isExpanded: Binding<Bool>, @ViewBuilder content: @escaping () -> Content)
Swift
๋ณต์‚ฌ
๊ทธ๋ฆฌ๊ณ  ํ•˜์œ„์— Content๋กœ ์›ํ•˜๋Š” ํ…์ŠคํŠธ๋ฅผ ๋„ฃ๊ฑฐ๋‚˜ ๋˜ ์ด์–ด์„œ DisclosureGroup์„ ๋งŒ๋“ค์–ด ๋„ฃ์„ ์ˆ˜๋„ ์žˆ๋‹ค.
์—ฌ๊ธฐ์„œ ์ค‘์š”ํ•œ๊ฑด ๋‘ DisclosureGroup์€ ์ƒํ•˜์œ„ ๊ฐœ๋…์œผ๋กœ ์†ํ•˜๊ณ  ์žˆ์ง€๋งŒ ํŽผ์นจ/์ˆจ๊น€์— ๋Œ€ํ•ด์„œ๋Š” ๋”ฐ๋กœ ๊ฐ€์ ธ๊ฐ€๊ฑฐ๋‚˜ ๊ฐ™์ด ๊ฐ€์ก€๊ฐˆ ์ˆ˜๋„ ์žˆ๋‹ค.
๋”ฐ๋กœ ๊ฐ€์ ธ๊ฐ€๋ ค๋ฉด ์•„๋ž˜์™€ ๊ฐ™์ด ๋ณ„๋„ ๋ณ€์ˆ˜๋กœ ์ปจํŠธ๋กค ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
import SwiftUI struct DisclosureGroupView: View { @State private var firstExpanded: Bool = false @State private var secondExpanded: Bool = true var body: some View { DisclosureGroup("1๋ฒˆ ๊ทธ๋ฃน", isExpanded: $firstExpanded) { Text("1๋ฒˆ ๊ทธ๋ฃน์— ์†ํ•œ ํ…์ŠคํŠธ") DisclosureGroup("2๋ฒˆ ๊ทธ๋ฃน", isExpanded: $secondExpanded) { Text("2๋ฒˆ ๊ทธ๋ฃน์— ์†ํ•œ ํ…์ŠคํŠธ") } } } }
Swift
๋ณต์‚ฌ
โ†’ ์ด๋ ‡๊ฒŒ ์ปค์Šคํ…€ํ•œ DisclosureGroup์„ ๋งŒ๋“ค์–ด ํŒŒ์ผ ๊ตฌ์กฐ์ฒ˜๋Ÿผ ๋ทฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‹ค.

OutlineGroup

Disclosure Views๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” View๊ฐ€ ํ•„์š”ํ•  ๋•Œ OutlineGroup์„ ์‚ฌ์šฉํ•˜๋ฉด ๋œ๋‹ค.
์ •์˜์—์„œ ๋งํ•œ ๋ฐ์ดํ„ฐ ๊ณ„์ธต ๊ตฌ์กฐ (ํด๋” ๊ณ„์ธต ๊ตฌ์กฐ)
์• ํ”Œ ์˜ˆ์ œ)
struct FileItem: Hashable, Identifiable { var id: Self { self } var name: String var children: [FileItem]? = nil var fileName: String { switch self.children { case nil: return "๐Ÿ“„ \(self.name)" case .some(let children): return children.isEmpty ? "๐Ÿ“‚ \(self.name)" : "๐Ÿ“ \(self.name)" } } } let data = FileItem(name: "users", children: [FileItem(name: "Zedd", 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: "Alan Walker", children: [FileItem(name: "Documents", children: []) ]) ])
Swift
๋ณต์‚ฌ
์ด๋ ‡๊ฒŒ FileItem ํƒ€์ž…์ด ์žˆ๋‹ค.
ํŒŒ์ผ์ด ์ž์‹์œผ๋กœ ๋˜ ํŒŒ์ผ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ children์˜ ํƒ€์ž…์€ [FileItem]์ด๊ณ ,
๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ๊ณ , ์•ˆ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ข… ํƒ€์ž…์€ [FileItem]? ์ด ๋œ๋‹ค.
๊ทธ๋ฆฌ๊ณ  fileName์€ ๋งŒ์•ฝ children์ด ์—†์œผ๋ฉด ํŒŒ์ผ ์ด๋ฆ„์„ ๋ณด์—ฌ์ฃผ๊ณ ,
์žˆ๋‹ค๋ฉด ํด๋” ์•„์ด์ฝ˜๊ณผ ํ•จ๊ป˜ ํด๋” ์ด๋ฆ„์„ ๋ณด์—ฌ์ค€๋‹ค.
OutlineGroup(root: Identifiable, children: KeyPath<Identifiable, _?>, content: (Identifiable) -> _)
Swift
๋ณต์‚ฌ
OutlineGroup์€ ์ด๋ ‡๊ฒŒ root์™€ children์„ ๋ฐ›๋Š”๋‹ค.
struct ContentView: View { let data = FileItem(...) var body: some View { NavigationView { Form { OutlineGroup(self.data, children: \.children) { item in Text("\(item.fileName)") } }.navigationTitle("ํŒŒ์ผ") } } }
Swift
๋ณต์‚ฌ

Reference

SwiftUI ) OutlineGroup / DisclosureGroup
์•ˆ๋…•ํ•˜์„ธ์š” :) Zedd์ž…๋‹ˆ๋‹ค. ์˜ค๋Š˜์€!! OutlineGroup๊ณผ DisclosureGroup์„ ๊ณต๋ถ€ํ•ด๋ณด๋ ค๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์• ํ”Œ ๋ฌธ์„œ์— ์žˆ๋Š” Hierarchical Views์„น์…˜์— ์žˆ๋Š” ์นœ๊ตฌ๋“ค์ด์—์š”! OutlineGroup disclosure views๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๋ฐ์ดํ„ฐ ๊ณ„์ธต ๊ตฌ์กฐ๋ฅผ ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋Š” View๊ฐ€ ํ•„์š”ํ•  ๋•Œ OutlineGroup์„ ์‚ฌ์šฉํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ •์˜์—์„œ ๋งํ•œ ๋ฐ์ดํ„ฐ ๊ณ„์ธต ๊ตฌ์กฐ...๋ผ๊ณ  ํ•˜๋ฉด ๊ฐ€์žฅ ์‰ฝ๊ฒŒ ์ƒ๊ฐ ํ•  ์ˆ˜ ์žˆ๋Š”๊ฒŒ ์ด๋Ÿฐ ํด๋” ๊ณ„์ธต ๊ตฌ์กฐ์ผ ๊ฒƒ ๊ฐ™์•„์š”. ์• ํ”Œ ์˜ˆ์ œ๋ฅผ ์‚ดํŽด๋ณผ๊ฒŒ์š”. ์ด๋ ‡๊ฒŒ FileItemํƒ€์ž…์ด ์žˆ์Šต๋‹ˆ๋‹ค. ํŒŒ์ผ์ด ์ž์‹์œผ๋กœ ๋˜ ํŒŒ์ผ์„ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์œผ๋ฏ€๋กœ children์˜ ํƒ€์ž…์€ [FileItem]์ด๊ณ , ๊ฐ€์งˆ์ˆ˜๋„ ์žˆ๊ณ  ์•ˆ๊ฐ€์งˆ์ˆ˜๋„ ์žˆ๊ธฐ๋•Œ๋ฌธ์— ์ตœ์ข… ํƒ€์ž…์€ [FileItem]?์ด ๋ฉ๋‹ˆ๋‹ค...
SwiftUI - DisclosureGroup & OutlineGroup
์•ˆ๋…•ํ•˜์„ธ์š”. ๊ทธ๋ฆฐ์ž…๋‹ˆ๋‹ค๐Ÿ ์ด๋ฒˆ ํฌ์ŠคํŒ…์—์„œ๋Š” SwiftUI์˜ Lists์— ์†ํ•ด์žˆ๋Š” ํƒ€์ž…์ธ DisclosureGroup & OutlineGroup์— ๋Œ€ํ•ด ํ•™์Šตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค๐Ÿ™Œ ์šฐ์„  ์ด ๋‘˜์ด ๋Œ€๋žต์ ์œผ๋กœ ์–ด๋–ค๊ฑด์ง€ ๊ฐ„๋‹จํžˆ ์„ค๋ช…ํ•ด๋ณผ๊ป˜์š”. ๋‹จ์ˆœํ•˜๊ฒŒ ์ƒ๊ฐํ•ด์„œ ์ ‘๊ณ  ํŽผ ์ˆ˜ ์žˆ๋Š” ํŒŒ์ผ์ธ ํŠธ๋ฆฌ ๊ตฌ์กฐ์˜ ํ˜•ํƒœ๋ฅผ ๊ฐ€์ง€๊ฒŒ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ทฐ๋ผ๊ณ  ๋ณด๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด์ •๋„๋กœ๋งŒ ์„ค๋ช…ํ•ด์„œ๋Š” ๊ฐ์ด ์•ˆ์˜ค์‹ค ์ˆ˜๋„ ์žˆ๊ฒ ์ง€๋งŒ ์‹ค์ œ๋กœ ์•„๋ž˜ ๊ตฌํ˜„๋œ๊ฑธ ๋ณด๋ฉด ๋ฐ”๋กœ ๋นก ์•„~ ์ด๋Ÿฐ๊ฑฐ ํ• ๊ฑฐ์—์š”๐Ÿ˜„ ์•„..! ์ฐธ๊ณ ๋กœ ์ด ๋‘๊ฐ€์ง€๋Š” SwiftUI๋ผ๊ณ  ๋‹ค ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฒƒ์ด ์•„๋‹ˆ๊ณ  iOS 14 ์ด์ƒ์—์„œ๋งŒ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค๐Ÿ•บ๐Ÿป ๊ทธ๋Ÿผ ์ด๊ฑด ์ฝ”๋“œ๊ฐ€ ๋” ์‰ฝ๊ฒŒ ์ดํ•ด๋  ์ˆ˜ ์žˆ์œผ๋‹ˆ ๋ฐ”๋กœ ๋ณธ๋ก ์œผ๋กœ ๊ฐ€๋ณผ๊ป˜์š”! DisclosureGroup? ์ œ์–ด์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ํ•˜์œ„ ์ปจํ…์ธ ๋ฅผ ํ‘œ์‹œํ•˜๊ฑฐ๋‚˜ ์ˆจ๊ธธ ์ˆ˜ ์žˆ๋Š” ๋ทฐ์ž…..