【问题标题】:Get Live Text when press button按下按钮时获取实时文本
【发布时间】:2021-11-18 04:56:37
【问题描述】:
UIAction.captureTextFromCamera(responder: context.coordinator, identifier: nil)

此方法必须先放置在菜单中才能使用。如果我想在按下 Button 的时候调用这个方法呢?

我想在 SwiftUI 中使用它,像这样

@State var text = ""

Text(text)

Menu {

                Button(action: {

                    // TODO: support live text

                }) {

                    Label("Live Text", systemImage: "camera.viewfinder")

                }

            } label: {

                Text("Hi")

            }

【问题讨论】:

  • UIButton 也符合UIResponder,我认为,所以它应该可以工作
  • 它需要 UIResponder & UIKeyInput 它不能直接在 SwiftUI Button 中工作,因为它没有任何地方可以放置文本。您必须使用同时具有的 UIKit 选项

标签: swift swiftui uikit ios15


【解决方案1】:
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()
    }
}

【讨论】:

  • VStack { Text(text) Menu { ScanTextView_UI(text: $text, type: .button) } label: { Text("2") } } 它不起作用
  • @Underthestars-zhy 不,看起来好像没有潜在的冲突。您必须使用 .buttonMenu 选项,如果您有更多操作,则必须以编程方式创建它们。
  • @Underthestars-zhy 我添加了一个小样本
  • @Iroem ipsum 看来我不能使用 uikit 菜单,有什么方法可以将 UIAction 与 SwiftUI 菜单结合起来
  • @Underthestars-zhy 怀疑...您可以轻松地将元素添加到 UIKit 菜单,但我认为您不能组合。毕竟 SwiftUI 元素只是 UIKit 对应元素的简单版本。你看到代码改变了吗?您可以在哪里添加操作?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-28
  • 2019-08-05
相关资源
最近更新 更多