如何从 Swift UI 中的不同应用程序将文本粘贴到文本字段
How to paste text on textfield from different app in Swift UI
我为 6 位数字创建了一个 OTP 字段,我想启用粘贴功能,例如我想将文本从 imessage 复制到我的应用程序的文本字段。我认为这在文本字段中是自动的,但是当我在文本字段中双击时,不会出现要求粘贴文本的对话框。我的剪贴板不是空的,因为我在其他不是 SwiftUI 的文本字段中尝试过它并且它有效。
由于我使用的 Xcode 的限制,我的文本字段被创建为许多解决方法视图。我只能用Xcode 12.3.
PS
如果有人也能帮助我,为什么我的小数键盘上缺少 完成 按钮。
这是我的代码:
import SwiftUI
@available(iOS 13.0, *)
class OTPViewModel: ObservableObject {
var numberOfFields: Int
init(numberOfFields: Int = 6) {
self.numberOfFields = numberOfFields
}
@Published var otpField = "" {
didSet {
guard otpField.count <= numberOfFields,
otpField.last?.isNumber ?? true else {
otpField = oldValue
return
}
if otpField.count == numberOfFields {
hideKeyboard()
}
}
}
@Published var isEditing = false
func otp(digit: Int) -> String {
guard otpField.count >= digit else {
return ""
}
return String(Array(otpField)[digit - 1])
}
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
@available(iOS 13.0, *)
struct OTPView: View {
@ObservedObject var viewModel = OTPViewModel()
private let textBoxWidth: CGFloat = 41
private let textBoxHeight = UIScreen.main.bounds.width / 8
private let spaceBetweenLines: CGFloat = 16
private let paddingOfBox: CGFloat = 1
private var textFieldOriginalWidth: CGFloat {
(textBoxWidth + CGFloat(18)) * CGFloat(viewModel.numberOfFields)
}
var body: some View {
Background {
VStack {
ZStack {
HStack (spacing: spaceBetweenLines) {
ForEach(1 ... viewModel.numberOfFields, id: \.self) { digit in
otpText(
text: viewModel.otp(digit: digit),
isEditing: viewModel.isEditing,
beforeCursor: digit - 1 < viewModel.otpField.count,
afterCursor: viewModel.otpField.count < digit - 1
)
}
} //: HSTACK
TextField("", text: $viewModel.otpField) { isEditing in
viewModel.isEditing = isEditing
}
.font(Font.system(size: 50, design: .default))
.offset(y: 10)
.frame(width: viewModel.isEditing ? 0 : textFieldOriginalWidth, height: textBoxHeight)
.textContentType(.oneTimeCode)
.foregroundColor(.clear)
.background(Color.clear)
.keyboardType(.decimalPad)
} //: ZSTACK
} //: VSTACK
} //: Background
.onTapGesture {
viewModel.hideKeyboard()
}
}
struct Background<Content: View>: View {
private var content: Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content()
}
var body: some View {
Color.clear
.contentShape(Rectangle())
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
.overlay(content)
}
}
@available(iOS 13.0, *)
private func otpText(
text: String,
isEditing: Bool,
beforeCursor: Bool,
afterCursor: Bool
) -> some View {
return Text(text)
.font(Font.custom("GTWalsheim-Regular", size: 34))
.frame(width: textBoxWidth, height: textBoxHeight)
.background(VStack{
Spacer()
.frame(height: 65)
ZStack {
Capsule()
.frame(width: textBoxWidth, height: 2)
.foregroundColor(Color(hex: "#BCBEC0"))
Capsule()
.frame(width: textBoxWidth, height: 2)
.foregroundColor(Color(hex: "#367878"))
.offset(x: (beforeCursor ? textBoxWidth : 0) + (afterCursor ? -textBoxWidth : 0))
.animation(.easeInOut, value: [beforeCursor, afterCursor])
.opacity(isEditing ? 1 : 0)
} //: ZSTACK
.clipped()
})
.padding(paddingOfBox)
}
}
有粘贴功能,但由于我的文本字段的框架。它超出了范围,无法在屏幕上看到。我调整了框架,现在粘贴出现了。我还修改了强调色以隐藏光标。
var body: some View {
VStack {
ZStack {
HStack (spacing: spaceBetweenLines) {
ForEach(1 ... viewModel.numberOfFields, id: \.self) { digit in
otpText(
text: viewModel.otp(digit: digit),
isEditing: viewModel.isEditing,
beforeCursor: digit - 1 < viewModel.otpField.count,
afterCursor: viewModel.otpField.count < digit - 1
)
}
} //: HSTACK
TextField("", text: $viewModel.otpField) { isEditing in
viewModel.isEditing = isEditing
}
.font(Font.system(size: 50, design: .default))
.offset(y: 10)
.frame(width: textFieldOriginalWidth, height: textBoxHeight) // What I changed
.textContentType(.oneTimeCode)
.foregroundColor(.clear)
.background(Color.clear)
.keyboardType(.decimalPad)
.accentColor(.clear)
} //: ZSTACK
} //: VSTACK
我为 6 位数字创建了一个 OTP 字段,我想启用粘贴功能,例如我想将文本从 imessage 复制到我的应用程序的文本字段。我认为这在文本字段中是自动的,但是当我在文本字段中双击时,不会出现要求粘贴文本的对话框。我的剪贴板不是空的,因为我在其他不是 SwiftUI 的文本字段中尝试过它并且它有效。
由于我使用的 Xcode 的限制,我的文本字段被创建为许多解决方法视图。我只能用Xcode 12.3.
PS
如果有人也能帮助我,为什么我的小数键盘上缺少 完成 按钮。
这是我的代码:
import SwiftUI
@available(iOS 13.0, *)
class OTPViewModel: ObservableObject {
var numberOfFields: Int
init(numberOfFields: Int = 6) {
self.numberOfFields = numberOfFields
}
@Published var otpField = "" {
didSet {
guard otpField.count <= numberOfFields,
otpField.last?.isNumber ?? true else {
otpField = oldValue
return
}
if otpField.count == numberOfFields {
hideKeyboard()
}
}
}
@Published var isEditing = false
func otp(digit: Int) -> String {
guard otpField.count >= digit else {
return ""
}
return String(Array(otpField)[digit - 1])
}
func hideKeyboard() {
UIApplication.shared.sendAction(#selector(UIResponder.resignFirstResponder), to: nil, from: nil, for: nil)
}
}
@available(iOS 13.0, *)
struct OTPView: View {
@ObservedObject var viewModel = OTPViewModel()
private let textBoxWidth: CGFloat = 41
private let textBoxHeight = UIScreen.main.bounds.width / 8
private let spaceBetweenLines: CGFloat = 16
private let paddingOfBox: CGFloat = 1
private var textFieldOriginalWidth: CGFloat {
(textBoxWidth + CGFloat(18)) * CGFloat(viewModel.numberOfFields)
}
var body: some View {
Background {
VStack {
ZStack {
HStack (spacing: spaceBetweenLines) {
ForEach(1 ... viewModel.numberOfFields, id: \.self) { digit in
otpText(
text: viewModel.otp(digit: digit),
isEditing: viewModel.isEditing,
beforeCursor: digit - 1 < viewModel.otpField.count,
afterCursor: viewModel.otpField.count < digit - 1
)
}
} //: HSTACK
TextField("", text: $viewModel.otpField) { isEditing in
viewModel.isEditing = isEditing
}
.font(Font.system(size: 50, design: .default))
.offset(y: 10)
.frame(width: viewModel.isEditing ? 0 : textFieldOriginalWidth, height: textBoxHeight)
.textContentType(.oneTimeCode)
.foregroundColor(.clear)
.background(Color.clear)
.keyboardType(.decimalPad)
} //: ZSTACK
} //: VSTACK
} //: Background
.onTapGesture {
viewModel.hideKeyboard()
}
}
struct Background<Content: View>: View {
private var content: Content
init(@ViewBuilder content: @escaping () -> Content) {
self.content = content()
}
var body: some View {
Color.clear
.contentShape(Rectangle())
.frame(width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height)
.overlay(content)
}
}
@available(iOS 13.0, *)
private func otpText(
text: String,
isEditing: Bool,
beforeCursor: Bool,
afterCursor: Bool
) -> some View {
return Text(text)
.font(Font.custom("GTWalsheim-Regular", size: 34))
.frame(width: textBoxWidth, height: textBoxHeight)
.background(VStack{
Spacer()
.frame(height: 65)
ZStack {
Capsule()
.frame(width: textBoxWidth, height: 2)
.foregroundColor(Color(hex: "#BCBEC0"))
Capsule()
.frame(width: textBoxWidth, height: 2)
.foregroundColor(Color(hex: "#367878"))
.offset(x: (beforeCursor ? textBoxWidth : 0) + (afterCursor ? -textBoxWidth : 0))
.animation(.easeInOut, value: [beforeCursor, afterCursor])
.opacity(isEditing ? 1 : 0)
} //: ZSTACK
.clipped()
})
.padding(paddingOfBox)
}
}
有粘贴功能,但由于我的文本字段的框架。它超出了范围,无法在屏幕上看到。我调整了框架,现在粘贴出现了。我还修改了强调色以隐藏光标。
var body: some View {
VStack {
ZStack {
HStack (spacing: spaceBetweenLines) {
ForEach(1 ... viewModel.numberOfFields, id: \.self) { digit in
otpText(
text: viewModel.otp(digit: digit),
isEditing: viewModel.isEditing,
beforeCursor: digit - 1 < viewModel.otpField.count,
afterCursor: viewModel.otpField.count < digit - 1
)
}
} //: HSTACK
TextField("", text: $viewModel.otpField) { isEditing in
viewModel.isEditing = isEditing
}
.font(Font.system(size: 50, design: .default))
.offset(y: 10)
.frame(width: textFieldOriginalWidth, height: textBoxHeight) // What I changed
.textContentType(.oneTimeCode)
.foregroundColor(.clear)
.background(Color.clear)
.keyboardType(.decimalPad)
.accentColor(.clear)
} //: ZSTACK
} //: VSTACK