SwiftUI 提供了一系列内置控件用于构建用户界面。这些控件都是结构体,遵循 View 协议,可以通过修饰器自定义外观和行为。

重点:

  • 文本控件的样式定制
  • 图片控件的使用方式
  • 按钮的事件处理
  • 输入控件的状态管理
  • 选择器的数据绑定

Text 和 TextField Link to heading

Text 支持富文本样式:

Text("标题文本")
    .font(.title)
    .bold()
    .foregroundColor(.blue)
    .lineLimit(2)
    .truncationMode(.tail)

// 文本组合
Text("价格: ")
    .foregroundColor(.gray) +
Text("¥99.9")
    .foregroundColor(.red)
    .bold()

TextField 处理文本输入:

struct InputView: View {
    @State private var username = ""
    @State private var isEditing = false
    
    var body: some View {
        TextField("请输入用户名", text: $username)
            .textFieldStyle(RoundedBorderTextFieldStyle())
            .onEditingChanged { editing in
                isEditing = editing
            }
            .onChange(of: username) { newValue in
                // 处理输入变化
            }
    }
}

安全输入:

SecureField("请输入密码", text: $password)
    .textContentType(.password)
    .autocapitalization(.none)

Button 和 Image Link to heading

基础按钮样式:

Button(action: {
    // 处理点击事件
}) {
    Text("确定")
        .foregroundColor(.white)
        .padding()
        .background(Color.blue)
        .cornerRadius(8)
}

// 图标按钮
Button(action: {}) {
    Image(systemName: "heart.fill")
        .foregroundColor(.red)
}

自定义按钮状态:

struct CustomButton: View {
    @State private var isPressed = false
    
    var body: some View {
        Button(action: {
            isPressed.toggle()
        }) {
            Text(isPressed ? "已选择" : "选择")
        }
        .buttonStyle(CustomButtonStyle())
    }
}

struct CustomButtonStyle: ButtonStyle {
    func makeBody(configuration: Configuration) -> some View {
        configuration.label
            .padding()
            .background(configuration.isPressed ? Color.gray : Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
            .scaleEffect(configuration.isPressed ? 0.95 : 1.0)
    }
}

Image 的使用:

// 系统图标
Image(systemName: "star.fill")
    .foregroundColor(.yellow)
    .font(.system(size: 20))

// 本地图片
Image("logo")
    .resizable()
    .aspectRatio(contentMode: .fit)
    .frame(width: 100, height: 100)

// 网络图片
AsyncImage(url: URL(string: "https://example.com/image.jpg")) { image in
    image
        .resizable()
        .aspectRatio(contentMode: .fit)
} placeholder: {
    ProgressView()
}

Toggle 和 Slider Link to heading

状态切换:

struct SettingsView: View {
    @State private var isOn = false
    @State private var volume: Double = 0.5
    
    var body: some View {
        Form {
            Toggle("开启通知", isOn: $isOn)
                .toggleStyle(SwitchToggleStyle(tint: .blue))
            
            Slider(value: $volume, in: 0...1) { editing in
                // 处理滑动状态
            }
            Text("音量: \(Int(volume * 100))%")
        }
    }
}

Picker 和 DatePicker Link to heading

选择器控件:

struct PickerView: View {
    @State private var selectedOption = 0
    @State private var selectedDate = Date()
    
    let options = ["选项1", "选项2", "选项3"]
    
    var body: some View {
        Form {
            // 普通选择器
            Picker("选择", selection: $selectedOption) {
                ForEach(0..<options.count, id: \.self) { index in
                    Text(options[index])
                }
            }
            .pickerStyle(MenuPickerStyle())
            
            // 日期选择器
            DatePicker(
                "选择日期",
                selection: $selectedDate,
                displayedComponents: [.date]
            )
            .datePickerStyle(GraphicalDatePickerStyle())
        }
    }
}

实用技巧 Link to heading

  1. 输入验证:
struct ValidatedInput: View {
    @State private var input = ""
    @State private var isValid = false
    
    var body: some View {
        TextField("输入", text: $input)
            .onChange(of: input) { newValue in
                isValid = validate(newValue)
            }
            .overlay(
                isValid ? 
                Image(systemName: "checkmark.circle.fill")
                    .foregroundColor(.green) :
                nil,
                alignment: .trailing
            )
    }
    
    func validate(_ text: String) -> Bool {
        // 验证逻辑
        return text.count >= 3
    }
}
  1. 自定义组合控件:
struct LabeledInput: View {
    let label: String
    @Binding var text: String
    
    var body: some View {
        HStack {
            Text(label)
                .frame(width: 80, alignment: .leading)
            TextField("", text: $text)
                .textFieldStyle(RoundedBorderTextFieldStyle())
        }
        .padding(.horizontal)
    }
}

常见问题 Link to heading

  1. TextField 键盘处理:
TextField("输入", text: $input)
    .keyboardType(.numberPad)
    .submitLabel(.done)
    .toolbar {
        ToolbarItemGroup(placement: .keyboard) {
            Spacer()
            Button("完成") {
                // 收起键盘
                UIApplication.shared.sendAction(
                    #selector(UIResponder.resignFirstResponder),
                    to: nil,
                    from: nil,
                    for: nil
                )
            }
        }
    }
  1. 图片加载失败处理:
AsyncImage(url: URL(string: imageUrl)) { phase in
    switch phase {
    case .empty:
        ProgressView()
    case .success(let image):
        image
            .resizable()
            .aspectRatio(contentMode: .fit)
    case .failure:
        Image(systemName: "photo")
            .foregroundColor(.gray)
    @unknown default:
        EmptyView()
    }
}
  1. 按钮点击区域优化:
Button(action: {}) {
    Text("点击")
}
.contentShape(Rectangle()) // 确保整个区域可点击
.allowsHitTesting(true)   // 启用点击

SwiftUI 的控件系统设计简洁直观,通过组合和修饰器可以实现丰富的界面效果。在实际开发中,需要注意控件的状态管理和用户交互体验的优化。