> For the complete documentation index, see [llms.txt](https://lochiwei.gitbook.io/ios/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://lochiwei.gitbook.io/ios/master/todo/exercises/collapsible.md).

# Collapsible

可以收合或展開的 HStack。

我們在 2 號的矩形上放了 .**onTapGesture**()，所以點它就可收合或展開整個橫向堆疊 (HStack)。

![💈 範例](https://1830103165-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5-JmwCZMKh_d7RfBaN%2F-MIhrqmt1Wkt8vmfZWRF%2F-MIhs6cNajCZmrCUD4c-%2Fcollapsible%20HStack.gif?alt=media\&token=1ed21bd1-4648-40ad-81ed-9c56d2262419)

{% tabs %}
{% tab title="📦  Collapsible" %}

```swift
/*
 * Thinking in SwiftUI, Ch. 4, Exercises
 *
 * ⭐️ Required: 🌀View + .if
 */

import SwiftUI
import PlaygroundSupport

// 📦 Collapsible
struct Collapsible<Item, Content: View>: View { 
    
    // the HStack is expanded or not
    @State private var expanded  = false 
    // items to present in the HStack
    var items: [Item] 
    
    // ⭐️ turn `Item` into `Content` view
    var content: (Item) -> Content
    
    // ⭐️ make i-th child view from items[i]
    func child(at i: Int) -> some View {
        
        // ⭐️ show child if expanded or last one
        let isLastOne = i == self.items.endIndex - 1
        let show = expanded || isLastOne
        
        // ⭐️ if collapsed, shrink width to 10
        let width: CGFloat? = show ? nil : 10
        
        return content(items[i]) 
            .frame(width: width)
            .animation(.default)
            .if(isLastOne){                                 // 🌀View + .if
                $0.onTapGesture { self.expanded.toggle() } 
        }
        
    } // child(at:)
    
    // body of Collapsible
    var body: some View {
        let s: CGFloat = expanded ? 8 : 0  // spacing
        return HStack(spacing: s) {
            ForEach(items.indices) { self.child(at: $0) }
        } 
    }
}
```

{% endtab %}

{% tab title="💈 範例" %}

```swift
let colors: [Color] = [ .red, .orange, .purple ]

// 🖼 content view
struct ContentView: View {
    var body: some View {
        Collapsible(items: [0, 1, 2]) { i in    // 📦  Collapsible
            Rectangle()
                .fill(colors[i])
                .overlay(Rectangle().stroke(Color.black, lineWidth: 3))
                .overlay(Text("\(i)"))
                .frame(height: 100)
        } //
            .shadow(radius: 8)
            .padding()
            .background(Color.gray)
    }
}

// 🏖 live view
PlaygroundPage.current.setLiveView(ContentView())
```

{% endtab %}

{% tab title="🧩  相依" %}

* [🌀 View](/ios/swiftui/view/view/view.md) + [.if()](/ios/custom/ext/view/.if.md)
  {% endtab %}

{% tab title="📘 參考" %}

* [x] Thinking in SwiftUI, Ch. 4, Exercises
  {% endtab %}
  {% endtabs %}
