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

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()
}