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.
273 lines
8.2 KiB
273 lines
8.2 KiB
import SwiftUI
|
|
|
|
// MARK: - 通用键盘工具栏组件
|
|
struct KeyboardToolbarView: View {
|
|
let onDone: () -> Void
|
|
let showDoneButton: Bool
|
|
let additionalButtons: [KeyboardToolbarButton]
|
|
|
|
init(
|
|
onDone: @escaping () -> Void = {},
|
|
showDoneButton: Bool = true,
|
|
additionalButtons: [KeyboardToolbarButton] = []
|
|
) {
|
|
self.onDone = onDone
|
|
self.showDoneButton = showDoneButton
|
|
self.additionalButtons = additionalButtons
|
|
}
|
|
|
|
var body: some View {
|
|
Group {
|
|
// 左侧按钮
|
|
HStack(spacing: 12) {
|
|
ForEach(additionalButtons.filter { $0.position == .left }, id: \.id) { button in
|
|
Button(action: button.action) {
|
|
HStack(spacing: 4) {
|
|
if let icon = button.icon {
|
|
Image(systemName: icon)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
Text(button.title)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
.foregroundColor(button.color)
|
|
}
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
|
|
// 右侧按钮
|
|
HStack(spacing: 12) {
|
|
ForEach(additionalButtons.filter { $0.position == .right }, id: \.id) { button in
|
|
Button(action: button.action) {
|
|
HStack(spacing: 4) {
|
|
if let icon = button.icon {
|
|
Image(systemName: icon)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
Text(button.title)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
.foregroundColor(button.color)
|
|
}
|
|
}
|
|
|
|
if showDoneButton {
|
|
Button("完成", action: onDone)
|
|
.foregroundColor(.blue)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
}
|
|
}
|
|
.toolbar {
|
|
ToolbarItemGroup(placement: .keyboard) {
|
|
// 左侧按钮
|
|
HStack(spacing: 12) {
|
|
ForEach(additionalButtons.filter { $0.position == .left }, id: \.id) { button in
|
|
Button(action: button.action) {
|
|
HStack(spacing: 4) {
|
|
if let icon = button.icon {
|
|
Image(systemName: icon)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
Text(button.title)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
.foregroundColor(button.color)
|
|
}
|
|
}
|
|
}
|
|
|
|
Spacer()
|
|
|
|
// 右侧按钮
|
|
HStack(spacing: 12) {
|
|
ForEach(additionalButtons.filter { $0.position == .right }, id: \.id) { button in
|
|
Button(action: button.action) {
|
|
HStack(spacing: 4) {
|
|
if let icon = button.icon {
|
|
Image(systemName: icon)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
Text(button.title)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
.foregroundColor(button.color)
|
|
}
|
|
}
|
|
|
|
if showDoneButton {
|
|
Button("完成", action: onDone)
|
|
.foregroundColor(.blue)
|
|
.font(.system(size: 16, weight: .medium))
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
// MARK: - 键盘工具栏按钮
|
|
struct KeyboardToolbarButton {
|
|
let id = UUID()
|
|
let title: String
|
|
let icon: String?
|
|
let color: Color
|
|
let position: ButtonPosition
|
|
let action: () -> Void
|
|
|
|
enum ButtonPosition {
|
|
case left, right
|
|
}
|
|
|
|
init(
|
|
title: String,
|
|
icon: String? = nil,
|
|
color: Color = .blue,
|
|
position: ButtonPosition = .right,
|
|
action: @escaping () -> Void
|
|
) {
|
|
self.title = title
|
|
self.icon = icon
|
|
self.color = color
|
|
self.position = position
|
|
self.action = action
|
|
}
|
|
}
|
|
|
|
// MARK: - 预定义的工具栏按钮
|
|
extension KeyboardToolbarButton {
|
|
static func clear(
|
|
text: Binding<String>,
|
|
position: ButtonPosition = .left
|
|
) -> KeyboardToolbarButton {
|
|
KeyboardToolbarButton(
|
|
title: "清空",
|
|
icon: "trash",
|
|
color: .red,
|
|
position: position
|
|
) {
|
|
text.wrappedValue = ""
|
|
}
|
|
}
|
|
|
|
static func copy(
|
|
text: String,
|
|
position: ButtonPosition = .left
|
|
) -> KeyboardToolbarButton {
|
|
KeyboardToolbarButton(
|
|
title: "复制",
|
|
icon: "doc.on.doc",
|
|
color: .blue,
|
|
position: position
|
|
) {
|
|
UIPasteboard.general.string = text
|
|
}
|
|
}
|
|
|
|
static func paste(
|
|
text: Binding<String>,
|
|
position: ButtonPosition = .left
|
|
) -> KeyboardToolbarButton {
|
|
KeyboardToolbarButton(
|
|
title: "粘贴",
|
|
icon: "doc.on.clipboard",
|
|
color: .green,
|
|
position: position
|
|
) {
|
|
if let pastedText = UIPasteboard.general.string {
|
|
text.wrappedValue = pastedText
|
|
}
|
|
}
|
|
}
|
|
|
|
static func next(
|
|
action: @escaping () -> Void,
|
|
position: ButtonPosition = .right
|
|
) -> KeyboardToolbarButton {
|
|
KeyboardToolbarButton(
|
|
title: "下一个",
|
|
icon: "arrow.right",
|
|
color: .blue,
|
|
position: position,
|
|
action: action
|
|
)
|
|
}
|
|
|
|
static func previous(
|
|
action: @escaping () -> Void,
|
|
position: ButtonPosition = .left
|
|
) -> KeyboardToolbarButton {
|
|
KeyboardToolbarButton(
|
|
title: "上一个",
|
|
icon: "arrow.left",
|
|
color: .blue,
|
|
position: position,
|
|
action: action
|
|
)
|
|
}
|
|
}
|
|
|
|
// MARK: - 预定义的工具栏样式
|
|
extension KeyboardToolbarView {
|
|
static func simple(onDone: @escaping () -> Void = {}) -> KeyboardToolbarView {
|
|
KeyboardToolbarView(onDone: onDone)
|
|
}
|
|
|
|
static func withClear(
|
|
text: Binding<String>,
|
|
onDone: @escaping () -> Void = {}
|
|
) -> KeyboardToolbarView {
|
|
KeyboardToolbarView(
|
|
onDone: onDone,
|
|
additionalButtons: [
|
|
.clear(text: text)
|
|
]
|
|
)
|
|
}
|
|
|
|
static func withCopyPaste(
|
|
text: Binding<String>,
|
|
onDone: @escaping () -> Void = {}
|
|
) -> KeyboardToolbarView {
|
|
KeyboardToolbarView(
|
|
onDone: onDone,
|
|
additionalButtons: [
|
|
.copy(text: text.wrappedValue),
|
|
.paste(text: text)
|
|
]
|
|
)
|
|
}
|
|
|
|
static func withNavigation(
|
|
onPrevious: @escaping () -> Void,
|
|
onNext: @escaping () -> Void,
|
|
onDone: @escaping () -> Void = {}
|
|
) -> KeyboardToolbarView {
|
|
KeyboardToolbarView(
|
|
onDone: onDone,
|
|
additionalButtons: [
|
|
.previous(action: onPrevious),
|
|
.next(action: onNext)
|
|
]
|
|
)
|
|
}
|
|
}
|
|
|
|
#Preview {
|
|
VStack(spacing: 16) {
|
|
Text("简单工具栏")
|
|
.font(.headline)
|
|
|
|
Text("带清空按钮的工具栏")
|
|
.font(.headline)
|
|
|
|
Text("带复制粘贴的工具栏")
|
|
.font(.headline)
|
|
|
|
Text("带导航的工具栏")
|
|
.font(.headline)
|
|
}
|
|
.padding()
|
|
} |