> 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/tutorials/ui-design/layout.md).

# 排版

用 VStack, HStack, ZStack, Spacer 排版。

## 重點

* 排版用：\
  `VStack`, `HStack`, `ZStack`, `Spacer`<br>

* 設定「字型級距」：\
  `text.font()`<br>

* 設定「字體粗細」：\
  `text.fontWeight()`<br>

* 讓圖片大小「隨外框調整」：\
  `image.resizable()`<br>

* 讓圖片「保持原比例」：\
  &#x20;`.aspectRatio(contentMode:)`

* 設定 view 的「內容對齊方式」：\
  `.frame(alignment:)`

* 要讓一個 view 爭取「最大的可用空間」，可用：\
  `.frame(maxWidth: .infinity, maxHeight: .infinity)`\
  \
  這通常用在本來是一個 pull-in 的 view (如：`VStack`)，如果本來就是一個 push-out 的 view (如：`Rectangle`) ，則不需做此設定。

{% hint style="danger" %}
注意：不要寫成 `frame(width: .infinity, height: .infinity)` 否則會當掉！
{% endhint %}

* 將 view 「裁剪成某個形狀」：\
  .**clipShape**()<br>
* 幫 view 「剪圓角」：\
  .**cornerRadius**()

{% hint style="danger" %}
注意：用 .**clipShape**() 與 .**cornerRadius**() 之前，不要用 .**shadow**() 之類的東西，否則一樣會被裁掉。
{% endhint %}

{% tabs %}
{% tab title="截圖" %}
![](https://1830103165-files.gitbook.io/~/files/v0/b/gitbook-legacy-files/o/assets%2F-M5-JmwCZMKh_d7RfBaN%2F-MFoeRnI4Dun6FgMGvRm%2F-MFogO_Bw4iEQ_RL9Rzn%2FUIDesign.jpg?alt=media\&token=665203da-e4c3-41e8-a4fa-ef6de39cff26)

{% endtab %}

{% tab title="main" %}

```swift
/*
 Design+Code - SwiftUI for iOS 13
 https://designcode.io/swiftui-layout-and-stacks
 */

import SwiftUI
import PlaygroundSupport

struct Card: View {
    var body: some View {
        // 卡片最外框
        VStack(spacing: 0) {
            // 卡片標題區：UIDesign & Swift logo
            HStack {
                // 文字區塊
                VStack(alignment: .leading) {   // 讓所有文字「靠左對齊」
                    Text("UI Design")
                        .font(.title)           // 字體加大
                        .fontWeight(.semibold)  // 字體加粗
                    Text("Certificate")
                        .foregroundColor(.blue)
                }
                
                Spacer()                        // 將「文字區塊」與「Swift 商標」推向兩側
                    
                // Swift 商標圖
                Image(uiImage:  imageLiteral(resourceName: "swift.png"))
                    .resizable()                  // 讓圖的大小「隨外框調整」（而不是用原尺寸）
                    .clipShape(Circle())          // 將圖修為「圓形」
                    .frame(width: 40, height: 40) // 限制尺寸為 40x40
                
            } // 卡片標題區
                .padding(.horizontal, 20)         // 左右留白 20
                .padding(.top, 20)                // 上面留白 20
                
            // 卡片設計圖
            Image(uiImage:  imageLiteral(resourceName: "UNESCO.png"))
                .resizable()                      // 讓圖的大小「隨外框調整」（而不是用原尺寸）
                .aspectRatio(contentMode: .fill)  // 讓圖片「保持原比例」⭐️
                // ⭐️ 設定圖片大小，並讓圖片「靠上緣對齊」（而不是預設的「置中」）
                .frame(width: 300, height: 140, alignment: .top)
            
        } // 卡片最外框
            // ⭐️ 讓卡片內容「靠上緣對齊」（而不是預設的「置中」）
            .frame(width: 340, height: 220, alignment: .top)
            .background(Color.black)
            .cornerRadius(20)                     // 將卡片「裁成圓角」
    }
}

struct ContentView: View {
    var body: some View {
        VStack {
            Card()
        } //
            // 讓外框自動採用「最大的寬度與高度」（而不是採用最小的）
            // ⚠️ 注意：
            //    不要寫成 `frame(width: .infinity, height: .infinity)` 
            //    否則會當掉！
            .frame(maxWidth: .infinity, maxHeight: .infinity)
            .background(Color.gray)
    }
}

PlaygroundPage.current.setLiveView(ContentView())
```

{% endtab %}

{% tab title="參考資料" %}
{% embed url="<https://designcode.io/swiftui-layout-and-stacks>" %}

Apple doc

* View [Rendering](https://developer.apple.com/documentation/swiftui/rendering)
* View [Layout](https://developer.apple.com/documentation/swiftui/layout)

{% endtab %}
{% endtabs %}
