Jak odrzucić klawiaturę, gdy dotykasz gdziekolwiek poza UITextField (w języku swift)?

Pracuję nad projektem, który ma UIViewController, na kontrolerze widoku znajduje się UIScrollView i UITextField na scrollview. w ten sposób: Próbuję odrzucić klawiaturę i ukryć ją po wpisaniu tekstu w polu tekstowym i stuknąć w dowolnym miejscu poza pole tekstowe. Wypróbowałem następujący kod:

override func viewDidLoad() {
    super.viewDidLoad()
    self.textField.delegate = self;
}

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
    self.view.endEditing(true)
}

Działa u mnie, gdy stukam poza przewijaniem, ale kiedy stukam w przewijanie, nic się nie dzieje, a klawiatura nie ukrywa.

Jest czy jest jakiś sposób na oddalenie klawiatury przy stukaniu gdziekolwiek poza pole tekstowe? dzięki

Author: White Hat, 2015-08-29

15 answers

Edited for Swift 4

Edit: Added @objc. Chociaż nie jest to najlepsza opcja dla wydajności, jedna jej instancja nie powinna powodować zbyt wielu problemów, dopóki nie pojawi się lepsze rozwiązanie.

Edytowano, aby naprawić, gdy trzeba wchodzić w interakcje z elementami za GestureRecognizer.

Edit: dzięki @Rao za wskazanie tego. Dodano tap.cancelsTouchesInView = false.

To powinno pomóc w posiadaniu wielu UITextView lub UITextField

Tworzenie rozszerzenia widoku kontroler. To działa znacznie płynniej dla mnie i z mniejszym kłopotem niż próba użycia .resignFirstResponder()

extension UIViewController
{
    func hideKeyboard()
    {
        let tap: UITapGestureRecognizer = UITapGestureRecognizer(
            target: self,
            action: #selector(UIViewController.dismissKeyboard))

        tap.cancelsTouchesInView = false
        view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard()
    {
        view.endEditing(true)
    }
}

Wywołanie self.hideKeyboard() w viewDidLoad

 86
Author: Matthew Bradshaw,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-04 17:24:35

Spróbuj tego, jest przetestowany i działa:

Dla Swift 3.0 / 4.0

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}

Dla Starszych Swift

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) {
    self.view.endEditing(true)
}
 51
Author: iAnurag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-21 10:53:07

W tym przypadku, istnieje UITapGesture jako jeden z wyborów. Próbowałem stworzyć przykładowy kod na wszelki wypadek. Jak to,

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var scrollView: UIScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        let tapGesture = UITapGestureRecognizer(target: self, action: "tap:")
        view.addGestureRecognizer(tapGesture)
    }

    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
}
 13
Author: pixyzehn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-29 01:34:06

Rozwiązanie robocze dla Swift 3, które współpracuje z ScrollView

class ViewController: UIViewController {

    @IBOutlet weak var textField: UITextField!
    @IBOutlet weak var scrollView: UIScrollView!

    override func viewDidLoad() {
        super.viewDidLoad()

        // The next line is the crucial part
        // The action is where Swift 3 varies from previous versions
        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tap(gesture:)))
        self.view.addGestureRecognizer(tapGesture)
    }

    func tap(gesture: UITapGestureRecognizer) {
        textField.resignFirstResponder()
    }
}

Kolejne pytanie mówiące o tej kwestii, do której się odwołałem i której użyłem. Zaakceptowana odpowiedź nie działa już w Swift 3. Aktualnie wybraną odpowiedzią powinna być odpowiedź poniżej.

 11
Author: Devbot10,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:45

Swift 3

override func viewDidLoad() {
    super.viewDidLoad()
    self.view.addGestureRecognizer(UITapGestureRecognizer(target: self.view, action: #selector(UIView.endEditing(_:))))
}
 11
Author: Giang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-13 04:53:52

Szczegóły

XCode 8.2.1, Swift 3

Zadanie

Ustaw UITapGestureRecognizer dla widoku UIViewController, który zamknie klawiaturę i uczyni tę funkcję właściwością bool UIView.

Złożona implementacja, ale użycie jest w jednej linii

Class TapGestureRecognizer

import UIKit

class TapGestureRecognizer: UITapGestureRecognizer {

    let identifier: String

    private override init(target: Any?, action: Selector?) {
        self.identifier = ""
        super.init(target: target, action: action)
    }

    init(target: Any?, action: Selector?, identifier: String) {
        self.identifier = identifier
        super.init(target: target, action: action)
    }

    static func == (left: TapGestureRecognizer, right: TapGestureRecognizer) -> Bool {
        return left.identifier == right.identifier
    }
}

Rozszerzenie UIView

import UIKit

extension UIView {

    private var disableKeybordWhenTappedGestureRecognizerIdentifier:String {
        return "disableKeybordWhenTapped"
    }

    private var disableKeybordWhenTappedGestureRecognizer: TapGestureRecognizer? {

        let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(UIView.hideKeyboard), identifier: disableKeybordWhenTappedGestureRecognizerIdentifier)

        if let gestureRecognizers = self.gestureRecognizers {
            for gestureRecognizer in gestureRecognizers {
                if let tapGestureRecognizer = gestureRecognizer as? TapGestureRecognizer, tapGestureRecognizer == hideKeyboardGesture, tapGestureRecognizer == hideKeyboardGesture {
                    return tapGestureRecognizer
                }
            }
        }
        return nil
    }

    @objc private func hideKeyboard() {
        endEditing(true)
    }

    var disableKeybordWhenTapped: Bool {

        set {
            let hideKeyboardGesture = TapGestureRecognizer(target: self, action: #selector(UIView.hideKeyboard), identifier: disableKeybordWhenTappedGestureRecognizerIdentifier)

            if let disableKeybordWhenTappedGestureRecognizer = self.disableKeybordWhenTappedGestureRecognizer {
                removeGestureRecognizer(disableKeybordWhenTappedGestureRecognizer)
                if gestureRecognizers?.count == 0 {
                    gestureRecognizers = nil
                }
            }

            if newValue {
                addGestureRecognizer(hideKeyboardGesture)
            }
        }

        get {
            return disableKeybordWhenTappedGestureRecognizer == nil ? false : true
        }
    }
}

Użycie

view.disableKeybordWhenTapped = true

Pełna Próbka

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        let textField = UITextField(frame: CGRect(x: 50, y: 50, width: 200, height: 30))
        textField.borderStyle = .roundedRect
        textField.placeholder = "Enter text"
        view.addSubview(textField)

        view.disableKeybordWhenTapped = true
    }
}
 5
Author: Vasily Bodnarchuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-02-12 11:58:57

Zobacz też

override func viewDidLoad() {
    var tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.handleTap))
    self.view.userInteractionEnabled = true
    self.view.addGestureRecognizer(tapGesture)
}

Wtedy twój uchwyt jest.

  func handleTap(sender: UITapGestureRecognizer) {
    self.view.endEditing(true)
}
 4
Author: handiansom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-27 02:41:51

Działa po dotknięciu poza obszarem wejściowym dla dowolnej liczby elementów wejściowych.

override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
        self.view.endEditing(true)
    }
 2
Author: Venkat Ram,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-19 10:47:27

Dla Swift 3

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    self.view.endEditing(true)
}
 2
Author: Davina Arnold,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-07 03:45:09

Miałem ten sam problem i w końcu go rozwiązałem !

Ustaw TapGestureRecognizer w Storyboardzie, a następnie wylot w kontrolerze ViewController

@IBOutlet var tapGesture: UITapGestureRecognizer!

Następnie Ustaw IBAction w kontrolerze ViewController

@IBAction func DismissKeyboard(sender: UITapGestureRecognizer)
{
 self.view.endEditing(true)
} 

Dodaj te linie do metody viewDidLoad

override func viewDidLoad()
{
    super.viewDidLoad()
    self.view.addGestureRecognizer(tapGesture)
}

I powinno działać

Mam nadzieję, że to pomoże !
 1
Author: Lynkz7,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-27 16:10:54

Każde dotknięcie pola tekstowego Wyłącz klawiaturę lub użyj resignfirstresponder

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
 UITouch *touch = [touches anyObject];
 if(![touch.view isMemberOfClass:[UITextField class]]) {
     [touch.view endEditing:YES];
 }
}
 1
Author: Miguel Monteiro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-04 18:39:25
func findAndResignFirstResponder(_ stView: UIView) -> Bool {

    if stView.isFirstResponder {
        stView.resignFirstResponder()
        return true
    }
    for subView: UIView in stView.subviews {
        if findAndResignFirstResponder(subView) {
            return true
        }
    }
    return false
}
 1
Author: Subhajit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-27 18:49:40

Stworzyłem tę metodę w Obj-C, która ukrywa klawiaturę bez względu na to, gdzie użytkownik aktualnie pisze:

//call this method
+ (void)hideKeyboard {
    //grab the main window of the application
    UIWindow *window = [UIApplication sharedApplication].keyWindow;
    //call our recursive method below
    [self resignResponderForView:window];
}

//our recursive method
+ (void)resignResponderForView:(UIView *)view {
    //resign responder from this view
    //If it has the keyboard, then it will hide the keyboard
    [view resignFirstResponder];
    //if it has no subviews, then return back up the stack
    if (view.subviews.count == 0)
        return;
    //go through all of its subviews
    for (UIView *subview in view.subviews) {
        //recursively call the method on those subviews
        [self resignResponderForView:subview];
    }
}

Mam nadzieję, że to przełoży się na Swift i ma sens. Może być wywołany w dowolnym miejscu w aplikacji i ukryje klawiaturę bez względu na to, na jakim VC jesteś lub cokolwiek.

 0
Author: AlexKoren,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-29 03:00:30

Przejdź do klawiatury Type i wybierz Default lub whatever you need the TextField for. Następnie zastąp metodę nazywaj ją jak chcesz, Zwykle nazywam ją touchingBegins. Poniżej jest to, czego zapomniałeś dodać

super.touchingBegins(touches, withEvent: event)
 }
 0
Author: Katz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-29 03:19:13

Wprowadź rozpoznawacz gestów stukania i ustaw go i uruchom.

Użyj kodu:

nameofyourtextfield .resignfirstresponder ()

 0
Author: kuni,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-19 10:59:37