Распознаватели быстрых жестов, добавленные в текстовое поле, становятся неработоспособными после того, как становится первым респондентом?

Я быстро добавил распознаватель жестов касания и двойного касания к текстовому полю, так что одиночное касание выполняет функцию, но двойное касание фактически заставляет текстовое поле стать первым респондентом. он перестает работать, хотя после того, как текстовое поле впервые становится первым респондентом. То есть текстовое поле работает как обычно, становясь первым респондентом при однократном нажатии, а не при двойном касании. Есть идеи, как поддерживать работу распознавателей жестов?


person Justin Leonard    schedule 19.06.2015    source источник
comment
эта логика не имеет для меня смысла. Почему вы хотите это сделать?   -  person DogCoffee    schedule 19.06.2015
comment
Текстовое поле показывает значение таймера обратного отсчета. Одно нажатие запускает или приостанавливает таймер. Двойное касание изменяет значение таймера. Не стесняйтесь предложить лучший способ добиться этого.   -  person Justin Leonard    schedule 19.06.2015
comment
См. Ответ Тушара. Проблема с редактированием значения? Я бы использовал метод, аналогичный реализации яблок.   -  person DogCoffee    schedule 19.06.2015


Ответы (3)


Другой подход:

Просто создайте «невидимое» представление поверх текстового поля и добавьте к нему распознаватели жестов.

    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
        }


    }
person Juan Carlos Ospina Gonzalez    schedule 19.06.2015
comment
Сработало отлично. Спасибо! Хотя этот невидимый вид не совсем невидимый. Но исправить это достаточно просто. Еще раз спасибо. - person Justin Leonard; 20.06.2015

Логически было бы проще, если бы вы вместо этого выполнили этот шаг:

  1. установить "editable" false для texField
  2. при реализации действия doubleTap сделайте текстовое поле доступным для редактирования до значения true и вызовите функцию beginFirstResponder, чтобы пользователь мог вводить текст.
  3. реализовать метод делегата текстового поля -textFieldDidEndEditing и снова сделать это textField недоступным для редактирования, установив для свойства "editable" значение false.
person Tushar    schedule 19.06.2015
comment
Боюсь, это не сработало. В то время как uitextview имеет редактируемое поле, uitextfield - нет. И использование, казалось бы, включенного поля отключает все касания, так что это тоже не сработало. - person Justin Leonard; 20.06.2015

У меня аналогичная проблема, я хочу, чтобы одно касание чередовало отображение и скрытие UIPicker.

Проблема в том, что UITextField добавляет свои собственные распознаватели жестов. Итак, создайте подкласс 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()
        }
    }
}

Если вы хотите скрыть выделение текста, вы также можете добавить следующее в производный класс (с помощью http://www.b2cloud.com.au/tutorial/dispting-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
    }
}
person Gary Hooper    schedule 11.09.2017