🔰Configuring Views

在設計 View 的時候,可以利用不同的方法,來達到同一個目的,如:「利用自製元件、View extension、ViewModifier、ViewBuilder」等。

範例

下面我們展示如何用不同的方式來寫「在 TextField 前加一個圖示」這個動作:

  1. 直接用 HStack

  2. 寫成一個「元件」IconTextField

  3. View extension:view.prefix(icon:)

  4. ViewModifierPrefixIcon

  5. ViewBuilder:IconTextFieldView

import SwiftUI
import PlaygroundSupport

// 表單
struct SignUpForm: View {
    
    @State private var username = ""
    @State private var email    = ""
    @State private var phone    = ""
    @State private var tel      = ""
    @State private var calendar = ""
    
    var body: some View {
        Form {
            // 表頭
            Text("表單").font(.headline)
                
            // ⭐️ 1. HStack
            HStack {
                Image(systemName: "person.circle.fill")
                TextField("姓名", text: $username)
                    .validate(username) { $0.count > 2 }      // ⭐️ 使用 Validation
            }
            
            // ⭐️ 2. 使用元件 `IconTextField`
            IconTextField(
                icon : "envelope.circle.fill", 
                title: "信箱", 
                text : $email
            )
            
            // ⭐️ 3. 使用 `View` extension
            TextField("0800-000-123", text: $phone)
                .textFieldStyle(RoundedBorderTextFieldStyle()) // ⭐️ 使用 TextFieldStyle
                .validate(phone) { $0.count > 2 }
                .prefix(icon: "phone.circle.fill")             // ⭐️ View extension
            
            // ⭐️ 4. 使用 `ViewModifier`
            // ⚠️ 注意:
            //    此處先用 PrefixIcon 再用 Validation,
            //    所以 Validation 的紅色外框會連「圖示」都框起來!
            TextField("(03) 000-1234", text: $tel)
                .modifier(PrefixIcon(name: "phone.circle.fill"))// ⭐️ ViewModifier
                .validate(tel) { $0.count > 1 }
            
            // ⭐️ 5. ViewBuilder
            IconTextFieldView(iconName: "calendar.circle.fill") {
                TextField("2020/09/14", text: $calendar)
            }
            
            Button(
                action: {  },
                label : { Text("確定") }
            )
            
        }.accentColor(.purple)
    }
}

// live view
struct ContentView: View {
    var body: some View {
        VStack {
            SignUpForm()
        }
    }
}

PlaygroundPage.current.setLiveView(ContentView())

參考資料

Last updated