如何在Flutter中禁用TextField的iOS「Scan Text」功能?
禁用iOS 15及以上版本TextField上下文菜单中的「Scan Text」按钮
核心思路是拦截「Scan Text」对应的系统动作,通过重写canPerformAction(_:withSender:)方法阻止该菜单项显示。以下是SwiftUI和UIKit两种场景的实现方案:
SwiftUI 实现方案
由于SwiftUI原生TextField未直接提供禁用该菜单项的API,需通过UIViewRepresentable包装UITextField来实现:
import SwiftUI struct NoScanTextField: UIViewRepresentable { @Binding var text: String func makeUIView(context: Context) -> UITextField { let textField = UITextField() textField.delegate = context.coordinator return textField } func updateUIView(_ uiView: UITextField, context: Context) { uiView.text = text } func makeCoordinator() -> Coordinator { Coordinator(text: $text) } class Coordinator: NSObject, UITextFieldDelegate { @Binding var text: String init(text: Binding<String>) { _text = text } func textFieldDidChangeSelection(_ textField: UITextField) { text = textField.text ?? "" } // 拦截Scan Text动作 override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { if action == #selector(UIResponder.captureTextFromCamera(_:)) { return false } return super.canPerformAction(action, withSender: sender) } } } // 使用示例 struct ContentView: View { @State private var inputText = "" var body: some View { NoScanTextField(text: $inputText) .padding() .border(Color.gray) } }
UIKit 实现方案
方式一:子类化UITextField
直接创建自定义TextField子类,重写动作拦截方法:
import UIKit class NoScanTextField: UITextField { override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { // 禁用Scan Text if action == #selector(UIResponder.captureTextFromCamera(_:)) { return false } return super.canPerformAction(action, withSender: sender) } } // 使用示例 let textField = NoScanTextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40)) textField.borderStyle = .roundedRect view.addSubview(textField)
方式二:通过ViewController的Delegate拦截
若不想子类化,可在TextField的代理所在类中重写动作拦截方法:
import UIKit class ViewController: UIViewController, UITextFieldDelegate { override func viewDidLoad() { super.viewDidLoad() let textField = UITextField(frame: CGRect(x: 20, y: 100, width: 300, height: 40)) textField.borderStyle = .roundedRect textField.delegate = self view.addSubview(textField) } // 拦截Scan Text动作 override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool { if action == #selector(UIResponder.captureTextFromCamera(_:)) { return false } return super.canPerformAction(action, withSender: sender) } }
原理说明
「Scan Text」对应的系统内置动作是UIResponder的captureTextFromCamera(_:)方法,当系统准备生成上下文菜单时,会调用canPerformAction(_:withSender:)判断是否显示对应菜单项,返回false即可隐藏该选项。
内容的提问来源于stack exchange,提问作者Kherel
相关产品推荐
相关产品推荐

