UIAction.captureTextFromCamera(responder: context.coordinator, identifier: nil)
This method must be placed in a Menu before it can be used. What if I want to call this method when I press the Button?
And I wanna use it in the SwiftUI, like this
@State var text = ""
Text(text)
Menu {
Button(action: {
// TODO: support live text
}) {
Label("Live Text", systemImage: "camera.viewfinder")
}
} label: {
Text("Hi")
}
CodePudding user response:
import SwiftUI
@available(iOS 15.0, *)
struct ScanTextView: View {
@State var text: String = ""
@State var message: String = ""
var body: some View {
VStack {
Text(message)
HStack{
TextField("Enter text",text: $text)
ScanTextView_UI(text: $text, type: .buttonMenu,imageSystemName: "ellipsis.circle", additionalActions: [
//https://developer.apple.com/documentation/uikit/uiaction
UIAction(title: "Refresh") { (action) in
//Just sample
self.message = "refresh"
},
UIAction(title: "Anything", image: UIImage(systemName: "checkmark")) { (action) in
//Just sample
self.message = "anything"
},
UIAction(title: "Clear message") { (action) in
//Just sample
self.message = ""
}
])
}.border(Color.red)
TextField("Enter text",text: $text)
.border(Color.yellow)
.toolbar(content: {
ToolbarItem(placement: .keyboard, content: {
ScanTextView_UI(text: $text, type: .buttonMenu)
})
})
ScanTextView_UI(text: $text, type: .textField, additionalActions: [
UIAction(title: "Anything", image: UIImage(systemName: "checkmark")) { (action) in
//Just sample
self.message = "anything"
}
]).border(Color.orange)
HStack{
TextField("Enter text",text: $text)
ScanTextView_UI(text: $text, type: .button)
}.border(Color.green)
}
}
}
@available(iOS 15.0, *)
struct ScanTextView_UI: UIViewRepresentable {
@Binding var text: String
let type: Types
var imageSystemName: String = "text.viewfinder"
var additionalActions: [UIAction] = []
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIView(context: Context) -> some UIView {
let textFromCamera = UIAction.captureTextFromCamera(responder: context.coordinator, identifier: nil)
let image = UIImage(systemName: imageSystemName)
//button
let button = UIButton(frame: .zero, primaryAction: textFromCamera)
button.setImage(image, for: .normal)
//buttonMenu
// A UIButton can hold the menu, it is a long press to get it to come up
let buttonMenu = UIButton()
var temp: [UIAction] = [textFromCamera]
for elem in additionalActions{
temp.append(elem)
}
let cameraMenu = UIMenu(children: temp)
buttonMenu.setImage(image, for: .normal)
buttonMenu.menu = cameraMenu
//TextField
// Or a textField
let toolbarItem = UIBarButtonItem(title: nil, image: image, primaryAction: textFromCamera, menu: nil)
var temp2: [UIBarButtonItem] = [toolbarItem]
for elem in additionalActions{
temp2.append(UIBarButtonItem(title: elem.title, image: elem.image, primaryAction: elem, menu: nil))
}
let textField = UITextField()
let bar = UIToolbar()
bar.items = temp2
bar.sizeToFit()
textField.inputAccessoryView = bar
textField.placeholder = "Enter text"
textField.delegate = context.coordinator
textField.text = text
var result: UIView = UIView()
switch type {
case .textField:
result = textField
case .buttonMenu:
result = buttonMenu
case .button:
if !additionalActions.isEmpty{
result = buttonMenu
}else{
result = button
}
}
return result
}
func updateUIView(_ uiView: UIViewType, context: Context) {
if uiView is UITextField{
(uiView as! UITextField).text = text
}
}
//Making the Coordinator a UIResponder as! UIKeyInput gives access to the text
class Coordinator: UIResponder, UIKeyInput, UITextFieldDelegate{
var hasText: Bool{
!parent.text.isEmpty
}
let parent: ScanTextView_UI
init(_ parent: ScanTextView_UI){
self.parent = parent
}
func insertText(_ text: String) {
//Update the @Binding
parent.text = text
}
func deleteBackward() { }
// MARK: UITextFieldDelegate
func textFieldDidBeginEditing(_ textField: UITextField) {
parent.text = textField.text ?? ""
}
}
enum Types{
case textField
case buttonMenu
case button
}
}
@available(iOS 15.0, *)
struct ActionMenuView_Previews: PreviewProvider {
static var previews: some View {
ScanTextView()
}
}