# adaptive column

[SwiftUI](/ios/swiftui.md) ⟩ [Layout](/ios/swiftui/view/layout.md) ⟩ [Grids](/ios/swiftui/view/layout/grids.md) ⟩ adaptive column

{% tabs %}
{% tab title="⭐️ 重點" %}
{% hint style="success" %} <mark style="color:purple;">**.adaptive(minimum:maximum)**</mark>:&#x20;

* a single [GridItem](/ios/swiftui/view/layout/grids/griditem.md) may represent <mark style="color:red;">**more than one column**</mark>.&#x20;
* SwiftUI will try to fit as many <mark style="color:red;">**minimum width**</mark> columns as possible, but once the number of columns is determined, these can grow up to the <mark style="color:red;">**maximum width**</mark> provided, so it fills the full space.&#x20;
* The method to determine how much space will be given to this GridItem is the same used for the [flexible](/ios/swiftui/view/layout/grids/griditem/flexible-column.md) case (<mark style="color:red;">**without the clamping**</mark>).
  {% endhint %}

{% hint style="danger" %}
the <mark style="color:purple;">**minimum**</mark> property of an <mark style="color:red;">**adaptive column**</mark> is **only** used to **compute** the <mark style="color:orange;">**number of items**</mark> inside that column, it's <mark style="color:red;">**NOT**</mark> the <mark style="color:orange;">**minimum width**</mark> of that column❗️👉 [objc](https://www.objc.io/blog/2020/11/23/grid-layout/)
{% endhint %}
{% endtab %}

{% tab title="💈例一" %}
{% embed url="<https://youtu.be/Sn7CMCrjP6I>" %}

{% hint style="warning" %}
本範例雖然只有指定<mark style="color:red;">**兩個**</mark> [**GridItem**](/ios/swiftui/view/layout/grids/griditem.md)：

```swift
let columns = [
    GridItem(.fixed(70)),                // ⭐ fixed column
    GridItem(.adaptive(minimum: 40))     // ⭐ adaptive column
]
```

但結果卻出現<mark style="color:red;">**三個欄位**</mark>，這主要是因為其中一個是 <mark style="color:red;">**adaptive column**</mark>，這種欄位可以一次<mark style="color:red;">**容納多個項目**</mark> (**cells**)。
{% endhint %}

![](/files/4sMljIcK4HStUY2qwplY)

⬆️ 需要： 👔 [ScrollVGridForEach](/ios/swiftui/view/layout/grids/vgridforeach.md)

```swift
// ------------------------
//     ⭐ Fixed Column
// ------------------------
//
//  always rendered at the specified width
//  (no matter how much space is available)

// ---------------------------
//     ⭐ Adaptive Column
// ---------------------------
//
// ⭐ tries to accommodate "as many items as possible"
// ⭐ the "minimum" property of an "adaptive column" is only used 
//    to compute how many items that column can accommodate, 
//    it's NOT the minimum width of that column❗️
//    (adaptive column's width could be SMALLER than this property)

// ⭐ 1.   (remaining width)
//       = (grid width) - (fixed widths) - (spaces between 2 columns)
//       = (200) - (70) - (8 * 1)
//       = (122)
//
// ⭐ 2. calculate (how many items) an adaptive column can accommodate:
//         (remaining width) - (first item) - (following items) > 0
//       given: 
//          minimum width = (40), spacing = (8) : ⭐ default
//          fist item = (40), following item = (8 + 40)
//
//       (122) - (40) - (48) * 1 =  34 > 0 ... ✅  (accommodate 2 items)
//       (122) - (40) - (48) * 2 = -14 < 0 ... ❌
//
// ⭐ 3.   (item width)
//       = [(remaining) - (spaces between 2 items)] / (2 items)
//       = [(122) - (8 * 1)] / 2
//       = 114 / 2
//       = 57  ............ (proposed size for each item) ⭐
// 
// ⭐ result:
//
// ╭──fixed──╮   ╭───── adaptive ──────╮ (one adaptive column)
// [   70    ][8][   57   ][8][   57   ]
//               ╰──item──╯   ╰──item──╯ (two grid items)

struct ContentView: View {
    
    let columns = [
        GridItem(.fixed(70)),                // ⭐ fixed column
        GridItem(.adaptive(minimum: 40))     // ⭐ adaptive column
    ]
    
    var body: some View {
        grid(columns)
    }
}

extension ContentView {
    
    /// a grid of swatches
    func grid(_ columns: [GridItem]) -> some View {
        // 👔 ScrollVGridForEach
        ScrollVGridForEach(0..<100, columns: columns){ 
            numberSwatch($0)
        }
        .frame(width: 200)        // grid width = scroll view width ⭐ 
        .border(Color.yellow)     // scroll view border (yellow)
        .padding()
        .border(Color.blue)       // padding border (blue)
        .frame(height: 300)
    }
    
    /// a color swatch with a number on it
    @ViewBuilder func numberSwatch(_ i: Int) -> some View {
        let color: Color = i % 3 == 0 ? .green : .pink
        color
            .opacity(0.3)
            .frame(height: 40)
            .overlay(Text("\(i)"))
    }
}
```

{% endtab %}

{% tab title="💈例二" %}
{% hint style="warning" %}
&#x20;雖然本範例的 <mark style="color:red;">**adaptive columen**</mark> 有 <mark style="color:purple;">**minimum**</mark> 屬性為 <mark style="color:red;">**70**</mark>：

```swift
let columns = [
    GridItem(.flexible(minimum: 140)),  // ⭐ flexible
    GridItem(.adaptive(minimum: 70))    // ⭐ adaptive
]
```

但此屬性<mark style="color:red;">**並非**</mark>**&#x20;adaptive column 的**<mark style="color:red;">**最小寬度**</mark>，而是用於<mark style="color:orange;">**計算能容納多少項目**</mark> (**cells**) 時使用。
{% endhint %}

![](/files/UzTlWKpE3XeWnzH78sNl)

```swift
struct ContentView: View {
    
    let columns = [
        GridItem(.flexible(minimum: 140)),  // ⭐ flexible
        GridItem(.adaptive(minimum: 70))    // ⭐ adaptive
    ]
    
    var body: some View {
        grid(columns)
    }
}
```

{% hint style="info" %}
欄位寬度的計算方式：👉 [grid layout algorithm](/ios/swiftui/view/layout/grids/layout-algorithm.md)
{% endhint %}

```swift
// r: remaining width
r = 200    // grid width
n = 2      // # of remaining cols

// r -= (fixed widths) + (spacing between cols)
r -= 8     // 192

// 1st col width
w1 = clamp(r/n)     // 192/2 = 96
   = 140            // clamped to [140, .inf)

// update r, n
r -= w1             // 192 - 140 = 52
n -= 1              // 1

// 2nd col width
w2 = clamp(r/n)      // 52/1 = 52
   = 52              // adaptive col is NOT clamped ⭐
```

{% endtab %}

{% tab title="📘 手冊" %}

* SwiftUI ⟩ Layout ⟩ [LazyVGrid](https://developer.apple.com/documentation/swiftui/lazyvgrid) ⟩ [.init(columns:alignment: ...)](https://developer.apple.com/documentation/swiftui/lazyvgrid/init\(columns:alignment:spacing:pinnedviews:content:\))
  {% endtab %}

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

* [x] objc ⟩ [SwiftUI’s Grid Views](https://www.objc.io/blog/2020/11/23/grid-layout/) ⭐️⭐️ - how **flexible**/**adaptive** columns behave. (💈例一)
  {% endtab %}

{% tab title="👥 相關" %}

* [grid layout algorithm](/ios/swiftui/view/layout/grids/layout-algorithm.md)
* [flexible column](/ios/swiftui/view/layout/grids/griditem/flexible-column.md)
  {% endtab %}
  {% endtabs %}


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://lochiwei.gitbook.io/ios/swiftui/view/layout/grids/griditem/adaptive-column.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
