You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
208 lines
5.7 KiB
208 lines
5.7 KiB
import SwiftUI
|
|
|
|
// MARK: - 通用输入字段组件
|
|
struct InputFieldView: View {
|
|
let title: String
|
|
let isRequired: Bool
|
|
let placeholder: String
|
|
let text: Binding<String>
|
|
let keyboardType: UIKeyboardType
|
|
let autocapitalization: UITextAutocapitalizationType
|
|
let icon: String?
|
|
let isSecure: Bool
|
|
let isFocused: Bool
|
|
let onFocusChange: (Bool) -> Void
|
|
|
|
init(
|
|
title: String,
|
|
isRequired: Bool = false,
|
|
placeholder: String,
|
|
text: Binding<String>,
|
|
keyboardType: UIKeyboardType = .default,
|
|
autocapitalization: UITextAutocapitalizationType = .sentences,
|
|
icon: String? = nil,
|
|
isSecure: Bool = false,
|
|
isFocused: Bool = false,
|
|
onFocusChange: @escaping (Bool) -> Void = { _ in }
|
|
) {
|
|
self.title = title
|
|
self.isRequired = isRequired
|
|
self.placeholder = placeholder
|
|
self.text = text
|
|
self.keyboardType = keyboardType
|
|
self.autocapitalization = autocapitalization
|
|
self.icon = icon
|
|
self.isSecure = isSecure
|
|
self.isFocused = isFocused
|
|
self.onFocusChange = onFocusChange
|
|
}
|
|
|
|
var body: some View {
|
|
VStack(alignment: .leading, spacing: 8) {
|
|
InputTitleView.required(title, icon: icon)
|
|
|
|
Group {
|
|
if isSecure {
|
|
SecureField(placeholder, text: text)
|
|
} else {
|
|
TextField(placeholder, text: text)
|
|
}
|
|
}
|
|
.textFieldStyle(RoundedBorderTextFieldStyle())
|
|
.keyboardType(keyboardType)
|
|
.autocapitalization(autocapitalization)
|
|
.onTapGesture {
|
|
onFocusChange(true)
|
|
}
|
|
.onChange(of: isFocused) { newValue in
|
|
onFocusChange(newValue)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 预定义的输入字段样式
|
|
extension InputFieldView {
|
|
static func text(
|
|
title: String,
|
|
isRequired: Bool = false,
|
|
placeholder: String,
|
|
text: Binding<String>,
|
|
icon: String? = nil,
|
|
isFocused: Bool = false,
|
|
onFocusChange: @escaping (Bool) -> Void = { _ in }
|
|
) -> InputFieldView {
|
|
InputFieldView(
|
|
title: title,
|
|
isRequired: isRequired,
|
|
placeholder: placeholder,
|
|
text: text,
|
|
icon: icon,
|
|
isFocused: isFocused,
|
|
onFocusChange: onFocusChange
|
|
)
|
|
}
|
|
|
|
static func email(
|
|
title: String,
|
|
isRequired: Bool = false,
|
|
placeholder: String,
|
|
text: Binding<String>,
|
|
icon: String? = nil,
|
|
isFocused: Bool = false,
|
|
onFocusChange: @escaping (Bool) -> Void = { _ in }
|
|
) -> InputFieldView {
|
|
InputFieldView(
|
|
title: title,
|
|
isRequired: isRequired,
|
|
placeholder: placeholder,
|
|
text: text,
|
|
keyboardType: .emailAddress,
|
|
autocapitalization: .sentences,
|
|
icon: icon,
|
|
isFocused: isFocused,
|
|
onFocusChange: onFocusChange
|
|
)
|
|
}
|
|
|
|
static func phone(
|
|
title: String,
|
|
isRequired: Bool = false,
|
|
placeholder: String,
|
|
text: Binding<String>,
|
|
icon: String? = nil,
|
|
isFocused: Bool = false,
|
|
onFocusChange: @escaping (Bool) -> Void = { _ in }
|
|
) -> InputFieldView {
|
|
InputFieldView(
|
|
title: title,
|
|
isRequired: isRequired,
|
|
placeholder: placeholder,
|
|
text: text,
|
|
keyboardType: .phonePad,
|
|
icon: icon,
|
|
isFocused: isFocused,
|
|
onFocusChange: onFocusChange
|
|
)
|
|
}
|
|
|
|
static func url(
|
|
title: String,
|
|
isRequired: Bool = false,
|
|
placeholder: String,
|
|
text: Binding<String>,
|
|
icon: String? = nil,
|
|
isFocused: Bool = false,
|
|
onFocusChange: @escaping (Bool) -> Void = { _ in }
|
|
) -> InputFieldView {
|
|
InputFieldView(
|
|
title: title,
|
|
isRequired: isRequired,
|
|
placeholder: placeholder,
|
|
text: text,
|
|
keyboardType: .URL,
|
|
autocapitalization: .sentences,
|
|
icon: icon,
|
|
isFocused: isFocused,
|
|
onFocusChange: onFocusChange
|
|
)
|
|
}
|
|
|
|
static func password(
|
|
title: String,
|
|
isRequired: Bool = false,
|
|
placeholder: String,
|
|
text: Binding<String>,
|
|
icon: String? = nil,
|
|
isFocused: Bool = false,
|
|
onFocusChange: @escaping (Bool) -> Void = { _ in }
|
|
) -> InputFieldView {
|
|
InputFieldView(
|
|
title: title,
|
|
isRequired: isRequired,
|
|
placeholder: placeholder,
|
|
text: text,
|
|
icon: icon,
|
|
isSecure: true,
|
|
isFocused: isFocused,
|
|
onFocusChange: onFocusChange
|
|
)
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
VStack(spacing: 16) {
|
|
InputFieldView.text(
|
|
title: "用户名",
|
|
isRequired: true,
|
|
placeholder: "请输入用户名",
|
|
text: .constant(""),
|
|
icon: "person"
|
|
)
|
|
|
|
InputFieldView.email(
|
|
title: "邮箱地址",
|
|
isRequired: true,
|
|
placeholder: "user@example.com",
|
|
text: .constant(""),
|
|
icon: "envelope"
|
|
)
|
|
|
|
InputFieldView.phone(
|
|
title: "电话号码",
|
|
isRequired: true,
|
|
placeholder: "+86 138 0013 8000",
|
|
text: .constant(""),
|
|
icon: "phone"
|
|
)
|
|
|
|
InputFieldView.password(
|
|
title: "密码",
|
|
isRequired: true,
|
|
placeholder: "请输入密码",
|
|
text: .constant(""),
|
|
icon: "lock"
|
|
)
|
|
}
|
|
.padding()
|
|
} |