Swift 添加到文本字段的手势识别器在成为第一响应者后无法操作?
Swift Gesture recognizers added to textfield inoperable after becomes first responder?
我在 swift 中的文本字段中添加了点击和双击手势识别器,因此单击执行功能但双击实际上使文本字段成为第一响应者。虽然在文本字段第一次成为第一响应者后它停止工作。也就是说,文本字段通过单击而不是双击成为第一响应者来正常运行。关于如何让我的手势识别器正常工作有什么想法吗?
从逻辑上讲,如果您改为执行以下步骤会更容易:
- 将 texField 设置为 "editable" false
- 在 doubleTap 操作实现上使文本字段可编辑为
true 并调用 becomeFirstResponder 以便用户可以键入。
- 实施文本字段委托方法 -textFieldDidEndEditing 并通过将 "editable" 属性 设置为 false 再次使该文本字段不可编辑。
另一种方法:
只需在文本字段顶部创建一个 'invisible' 视图并向其中添加手势识别器
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self;
}
override func viewDidAppear(animated: Bool) {
let tap1 = UITapGestureRecognizer(target: self, action: "onSingleTap")
let tap2 = UITapGestureRecognizer(target: self, action: "onDoubleTap")
tap2.numberOfTapsRequired = 2
// create a view and put it on top of the textfield
// here created at viewDidAppear for example but you can do it better
var dummieView = UIView(frame: self.textField.frame)
dummieView.backgroundColor = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.25)
self.view.addSubview(dummieView)
dummieView.addGestureRecognizer(tap1)
dummieView.addGestureRecognizer(tap2)
}
func onSingleTap(){
println("custom single tap")
if self.textField.isFirstResponder() {
self.textField.resignFirstResponder()
}
}
func onDoubleTap(){
println("double tap")
self.textField.becomeFirstResponder()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if self.textField.isFirstResponder() {
self.textField.resignFirstResponder()
}
return true
}
}
我有类似的问题,想要通过单击来交替显示和隐藏 UIPicker。
问题是 UITextField 添加了自己的手势识别器。因此,subclass UITextField 并添加您自己的,但不允许添加默认手势识别器。
class MyTextField: UITextField
{
fileprivate var tap1Gesture: UITapGestureRecognizer?
fileprivate var tap2Gesture: UITapGestureRecognizer?
required init?( coder aDecoder: NSCoder )
{
super.init( coder: aDecoder )
gestureRecognizers = nil
tap1Gesture = UITapGestureRecognizer( target: self, action: #selector( tapped1( _: ) ) )
addGestureRecognizer( tap1Gesture! )
tap2Gesture = UITapGestureRecognizer( target: self, action: #selector( tapped2( _: ) ) )
tap2Gesture.numberOfTapsRequired = 2
addGestureRecognizer( tap2Gesture! )
}
override func addGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer)
{
if gestureRecognizer == tap1Gesture || gestureRecognizer == tap2Gesture
{
super.addGestureRecognizer( gestureRecognizer )
}
}
internal func tapped1( _ sender: UITapGestureRecognizer )
{
// Do your "performs a function"
}
internal func tapped2( _ sender: UITapGestureRecognizer )
{
if self.isFirstResponder
{
_ = self.resignFirstResponder()
}
else
{
self.becomeFirstResponder()
}
}
}
如果您想隐藏文本选择,您还可以将以下内容添加到派生的 class(借助帮助 http://www.b2cloud.com.au/tutorial/disabling-the-caret-and-text-entry-in-uitextfields/):
extension MyTextField
{
override var selectedTextRange: UITextRange?
{
get { return nil }
set { return }
}
override func canPerformAction( _ action: Selector, withSender sender: Any? ) -> Bool
{
return false
}
override func caretRect( for position: UITextPosition ) -> CGRect
{
return .zero
}
}
我在 swift 中的文本字段中添加了点击和双击手势识别器,因此单击执行功能但双击实际上使文本字段成为第一响应者。虽然在文本字段第一次成为第一响应者后它停止工作。也就是说,文本字段通过单击而不是双击成为第一响应者来正常运行。关于如何让我的手势识别器正常工作有什么想法吗?
从逻辑上讲,如果您改为执行以下步骤会更容易:
- 将 texField 设置为 "editable" false
- 在 doubleTap 操作实现上使文本字段可编辑为 true 并调用 becomeFirstResponder 以便用户可以键入。
- 实施文本字段委托方法 -textFieldDidEndEditing 并通过将 "editable" 属性 设置为 false 再次使该文本字段不可编辑。
另一种方法:
只需在文本字段顶部创建一个 'invisible' 视图并向其中添加手势识别器
import UIKit
class ViewController: UIViewController, UITextFieldDelegate {
@IBOutlet weak var textField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
textField.delegate = self;
}
override func viewDidAppear(animated: Bool) {
let tap1 = UITapGestureRecognizer(target: self, action: "onSingleTap")
let tap2 = UITapGestureRecognizer(target: self, action: "onDoubleTap")
tap2.numberOfTapsRequired = 2
// create a view and put it on top of the textfield
// here created at viewDidAppear for example but you can do it better
var dummieView = UIView(frame: self.textField.frame)
dummieView.backgroundColor = UIColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.25)
self.view.addSubview(dummieView)
dummieView.addGestureRecognizer(tap1)
dummieView.addGestureRecognizer(tap2)
}
func onSingleTap(){
println("custom single tap")
if self.textField.isFirstResponder() {
self.textField.resignFirstResponder()
}
}
func onDoubleTap(){
println("double tap")
self.textField.becomeFirstResponder()
}
func textFieldShouldReturn(textField: UITextField) -> Bool {
if self.textField.isFirstResponder() {
self.textField.resignFirstResponder()
}
return true
}
}
我有类似的问题,想要通过单击来交替显示和隐藏 UIPicker。
问题是 UITextField 添加了自己的手势识别器。因此,subclass UITextField 并添加您自己的,但不允许添加默认手势识别器。
class MyTextField: UITextField
{
fileprivate var tap1Gesture: UITapGestureRecognizer?
fileprivate var tap2Gesture: UITapGestureRecognizer?
required init?( coder aDecoder: NSCoder )
{
super.init( coder: aDecoder )
gestureRecognizers = nil
tap1Gesture = UITapGestureRecognizer( target: self, action: #selector( tapped1( _: ) ) )
addGestureRecognizer( tap1Gesture! )
tap2Gesture = UITapGestureRecognizer( target: self, action: #selector( tapped2( _: ) ) )
tap2Gesture.numberOfTapsRequired = 2
addGestureRecognizer( tap2Gesture! )
}
override func addGestureRecognizer(_ gestureRecognizer: UIGestureRecognizer)
{
if gestureRecognizer == tap1Gesture || gestureRecognizer == tap2Gesture
{
super.addGestureRecognizer( gestureRecognizer )
}
}
internal func tapped1( _ sender: UITapGestureRecognizer )
{
// Do your "performs a function"
}
internal func tapped2( _ sender: UITapGestureRecognizer )
{
if self.isFirstResponder
{
_ = self.resignFirstResponder()
}
else
{
self.becomeFirstResponder()
}
}
}
如果您想隐藏文本选择,您还可以将以下内容添加到派生的 class(借助帮助 http://www.b2cloud.com.au/tutorial/disabling-the-caret-and-text-entry-in-uitextfields/):
extension MyTextField
{
override var selectedTextRange: UITextRange?
{
get { return nil }
set { return }
}
override func canPerformAction( _ action: Selector, withSender sender: Any? ) -> Bool
{
return false
}
override func caretRect( for position: UITextPosition ) -> CGRect
{
return .zero
}
}