Bagaimana Anda mengabaikan keyboard saat mengedit UITextField


181

Saya tahu bahwa saya perlu memberi tahu UITextField saya untuk mengundurkan diri sebagai responden pertama ketika saya ingin menghapus keyboard, tetapi saya tidak yakin bagaimana mengetahui kapan pengguna telah menekan tombol "Selesai" pada keyboard. Apakah ada pemberitahuan yang dapat saya perhatikan?


2
[self.view endEditing: YES]; dalam sentuhan mulai delegasi adalah solusi terbaik
Zar E Ahmer

Jawaban:


351

Saya mengatur delegasi UITextFieldke ViewControllerkelas saya .

Di kelas itu saya menerapkan metode ini sebagai berikut:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    [textField resignFirstResponder];
    return NO;
}

Lihat contoh di atas ... kawat yang menggunakan IntefaceBuilder ke tindakan pada apa pun yang Anda gunakan sebagai pengontrol Anda ... setiap kali pengguna menolak sistem entri teks (tekan selesai), ini akan dipanggil ...
Jason Coco

2
Salah satu dari ini akan berfungsi - bidang teks mengirimkan aksinya ketika pengguna menekan tombol Kembali ("Selesai", apa pun), dan juga mengirimkan delegasinya -textFieldShouldReturn :.
Noah Witherspoon

BTW - ini juga berfungsi untuk UISearchBar. Sebagai contoh, kode saya, saya punya anggota IBOutlet searchBarTusb; Ketika 'kunci kembali' (UIReturnKeySearch) saya diklik, - (batal) searchBarSearchButtonClicked :, saya meletakkan pernyataan [searchBarTusb resignFirstResponder]; Perhatikan juga, 'kunci kembali' diatur di NIB menggunakan Interface Builder.
mobibob

Mengapa kembali NObukan YES?
Iulian Onofrei

@IulianOnofrei Perilaku default tombol kembali adalah menambahkan garis kembali dan menjaga layar keyboard. Dengan kembali NOAnda menghindari menambahkan baris kembali ke teks.
kubi

47

Jika Anda menghubungkan acara DidEndOnExit dari bidang teks ke tindakan (IBAction) di InterfaceBuilder, itu akan dikirim ketika pengguna menolak keyboard (dengan tombol kembali) dan pengirim akan menjadi referensi ke UITextField yang memecat acara tersebut.

Sebagai contoh:

-(IBAction)userDoneEnteringText:(id)sender
{
    UITextField theField = (UITextField*)sender;
    // do whatever you want with this text field
}

Lalu, di InterfaceBuilder, tautkan acara DidEndOnExit dari bidang teks ke tindakan ini di controller Anda (atau apa pun yang Anda gunakan untuk menautkan acara dari UI). Setiap kali pengguna memasukkan teks dan mengabaikan bidang teks, pengontrol akan dikirimi pesan ini.


Satu-satunya peristiwa yang sepertinya berfungsi adalah textFieldDidEndEditing, yang menyatakan itu hanya dikirim setelah UITextField mengundurkan diri status responden pertama. Bagaimana saya tahu kapan saya harus mengundurkan diri dari status responden pertama?
kubi

Saya minta maaf tentang terminologi ... itu bukan pemberitahuan (acara) yang sebenarnya ... Saya akan mengedit jawaban saya dengan contoh dan penjelasan cepat, jadi lihat itu :)
Jason Coco

1
Untuk memperjelas jawaban ini, textField mengirimkan acara "Did End On Exit" ketika Anda menekan tombol kembali, jadi itulah yang Anda perlu tautkan ke controller Anda. Saya pikir metode ini lebih mudah daripada yang saya jelaskan di atas.
kubi

2
bisakah Anda mengedit jawaban ini sehingga ia menyebutkan acara WHICH untuk ditransfer, tolong? Ini jelas lebih baik daripada mengatur delegasi.
Dan Rosenstark

1
Ingin memvotasikan jawaban ini, tetapi tidak bisa sampai menyebutkan acara DidEndOnExit. Seseorang dengan hak istimewa edit silakan membuat perubahan jika OP tidak mau?
James Hart

32

Anda juga dapat membuat metode di controller Anda

 -(IBAction)editingEnded:(id)sender{
    [sender resignFirstResponder]; 
}

dan kemudian di Inspektur Koneksi di IB menghubungkan Acara "Did End On Exit" untuk itu.


1
Ini hampir tidak benar, atau setidaknya tidak tepat. Dengan berlangganan ke DidEndOnExitacara tersebut, Anda tidak perlu menelepon resignFirstResponder. Anda dapat menguji ini dengan meletakkan breakpoint simbolis pada [UIResponder resignFirstResponder]. Perhatikan bahwa meskipun jika Anda tidak memanggil resignFirstResponder, itu masih dipanggil oleh sistem. Ini dijelaskan dalam buku bagus Matt Neuburg: apeth.com/iOSBook/…
Chris Conover

19

kubi, terima kasih. Kode Anda berfungsi. Untuk menjadi eksplisit (untuk pemula seperti) seperti yang Anda katakan Anda harus mengatur UITextField's delegateagar sama dengan ViewController di mana bidang teks berada. Anda dapat melakukan ini di mana pun Anda mau. Saya memilih viewDidLoadmetode.

- (void)viewDidLoad 
{
    // sets the textField delegates to equal this viewController ... this allows for the keyboard to disappear after pressing done
    daTextField.delegate = self;
}

Jika Anda menambahkan bidang teks ke storyboard atau NIB Anda, Anda dapat mengatur bidang teks di delegatesana juga. Anda tidak harus melakukan ini secara terprogram, seperti ditunjukkan di atas. Kedua pendekatan tersebut berfungsi dengan baik.
Rob

18

Berikut adalah trik untuk mendapatkan perilaku pemberhentian keyboard otomatis tanpa kode sama sekali. Di nib, edit objek proxy Responder Pertama di inspektur Identitas, tambahkan tindakan responden pertama yang baru; sebut saja itu dummy:. Sekarang kaitkan kejadian Did End on Exit dari bidang teks ke dummy:tindakan objek proxy Responder Pertama. Itu dia! Karena acara Did End on Exit bidang teks sekarang memiliki pasangan tindakan-target, bidang teks secara otomatis menolak keyboard-nya ketika pengguna mengetuk Return; dan karena tidak ada penalti karena tidak menemukan penangan untuk pesan yang dikirim ke rantai responden, aplikasi tidak macet meskipun tidak ada implementasi di dummy:mana pun.


@ tikar saya menemukan bahwa JIKA saya menambahkan segue bersantai DAN menghubungkan acara didEndOnExit KEMUDIAN segue bersantai akan dipicu setelah menekan Return. Tanpa koneksi acara, segue tidak terpicu. Hebat tapi Hah? Ada komentar? BTW: Saya punya buku Swift (selesai) dan iOS10 (pada bab 6) Anda. Mereka sangat membantu saya!
Verticon

@Verticon pertanyaan dan jawaban tidak ada hubungannya dengan segues, jadi saya tidak mengerti masalah ... :( ini murni tentang pemberhentian keyboard
matt

@ tikar Maaf, teman. Saya mendukung piggy karena 1) Saya menemukan utas ini ketika saya berhadapan dengan bagaimana menangani kunci pengembalian UITextField; dan 2) itu adalah kesempatan untuk berinteraksi dengan Anda (thx for da books). Tidak ada "masalah". Hanya kurangnya pemahaman di pihak saya tentang mengapa / bagaimana cara kerjanya.
Verticon

@Verticon Saya minta maaf karena tidak bisa membantu. Jangan ragu untuk merumuskan pertanyaan baru dengan lebih banyak info (proyek demo?) Dan blip saya, jika saya bisa berguna.
matt


11

Cukup tambahkan

[textField endEditing:YES];

di mana Anda ingin menonaktifkan keyboard dan menampilkan tampilan pemilih.


10

Di Swift Anda dapat menulis IBAction di Controller dan mengatur event Did End On Exit dari bidang teks ke action tersebut

@IBAction func returnPressed(sender: UITextField) {
    self.view.endEditing(true)
}

5

Swift 4.2 dan itu akan bekerja 100%

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!


    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self

    }

    // hide key board when the user touches outside keyboard

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

    // user presses return key

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        textField.resignFirstResponder()
        return true
    }

}

4

Anda juga bisa menggunakan

 - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event 
  {

   [self.yourTextField resignFirstResponder];

  }

Yang terbaik jika Anda memiliki banyak Uitextfield:

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
 {    
     [self.view endEditing:YES];
 }

2

Inilah yang harus saya lakukan untuk membuatnya berfungsi, dan saya pikir perlu bagi siapa pun dengan Papan Tombol untuk keyboard (atau yang lainnya tanpa tombol selesai:

  1. Saya mengubah UIView di ViewController menjadi UIControl.
  2. Saya membuat fungsi yang disebut

    -(IBAction)backgroundIsTapped:(id)sender

Ini juga didefinisikan dalam file .h.

Setelah ini, saya ditautkan ke bit 'touch down' untuk ViewController di Interface Builder.

Dalam fungsi 'latar belakang disadap', saya letakkan ini:

    [answerField resignFirstResponder];

Hanya ingat untuk mengubah 'answerField' ke nama UITextField yang ingin Anda hapus keyboardnya (jelas pastikan UITextField Anda didefinisikan seperti di bawah ini :)

    IBOutlet UITextField * <nameoftextfieldhere>;

Saya tahu topik ini mungkin sudah lama mati ... tapi saya berharap ini akan membantu seseorang, di suatu tempat!


..tapi itu tidak berfungsi dengan baik jika pengguna mengetuk kontrol lain.
ragnarius

2

Anda akan melihat bahwa metode "textFieldShouldReturn" menyediakan objek bidang teks yang telah menekan tombol DONE. Jika Anda mengatur TAG Anda dapat mengaktifkan bidang teks itu. Atau Anda dapat melacak dan membandingkan penunjuk objek dengan beberapa nilai anggota yang disimpan oleh penciptanya.

Pendekatan saya seperti ini untuk belajar mandiri:

- (BOOL)textFieldShouldReturn:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    bool fDidResign = [textField resignFirstResponder];

    NSLog(@"%s: did %resign the keyboard", __FUNCTION__, fDidResign ? @"" : @"not ");

    return fDidResign;
}

Sementara itu, saya memasukkan tes "validasi" yang menyangkal pengunduran diri berikut. Ini hanya untuk ilustrasi, jadi jika pengguna mengetik TIDAK! ke lapangan, tidak akan diberhentikan. Perilaku itu seperti yang saya inginkan, tetapi urutan output tidak seperti yang saya harapkan.

- (BOOL)textFieldShouldEndEditing:(UITextField *)textField {
    NSLog(@"%s", __FUNCTION__);

    if( [[textField text] isEqualToString:@"NO!"] ) {
        NSLog(@"%@", textField.text);
        return NO;
    } else {
        return YES;
    }
}

Berikut ini adalah output NSLog saya untuk penolakan ini diikuti oleh penerimaan. Anda akan melihat bahwa saya mengembalikan hasil pengunduran diri, tetapi saya mengharapkannya mengembalikan FALSE kepada saya untuk melaporkan kembali kepada penelepon ?! Selain itu, ia memiliki perilaku yang diperlukan.

13.313 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
13.327 StudyKbd [109: 207] TIDAK!
13.333 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: memang mengundurkan diri dari keyboard
59.891 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd [109: 207] - [StudyKbdViewController doneEditText]: TIDAK
59.928 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: memang mengundurkan diri dari keyboard

1
dapatkah kau jelaskan .. jika aku mengembalikan TIDAK atau YA dalam kedua kasus hal yang sama terjadi sehingga apa kebutuhan mengembalikan ya dalam metode delegasi textFieldShouldReturn
K. Jaiswal

1

Berikut ini adalah cara yang cukup bersih untuk mengakhiri edisi dengan Return Key atau sentuhan di latar belakang.

Di pembangun Antarmuka, sisipkan bidang Anda dalam tampilan kelas UIFormView

Apa kelas ini:

  • Secara otomatis melampirkan dirinya sebagai delegasi bidang (Entah terbangun dari nib, atau ditambahkan secara manual)
  • Simpan referensi pada bidang yang diedit saat ini
  • Singkirkan keyboard saat kembali atau sentuh di latar belakang

Ini kodenya:

Antarmuka

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

-(BOOL)textFieldValueIsValid:(UITextField*)textField;
-(void)endEdit;

@end

Penerapan

#import "UIFormView.h"

@implementation UIFormView
{
    UITextField* currentEditingTextField;
}

// Automatically register fields

-(void)addSubview:(UIView *)view
{
    [super addSubview:view];
    if ([view isKindOfClass:[UITextField class]]) {
        if ( ![(UITextField*)view delegate] ) [(UITextField*)view setDelegate:self];
    }
}

// UITextField Protocol

-(void)textFieldDidBeginEditing:(UITextField *)textField
{
    currentEditingTextField = textField;
}

-(void)textFieldDidEndEditing:(UITextField *)textField
{
    currentEditingTextField = NULL;
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    [self endEdit];
}

- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
    if ([self textFieldValueIsValid:textField]) {
        [self endEdit];
        return YES;
    } else {
        return NO;
    }
}

// Own functions

-(void)endEdit
{
    if (currentEditingTextField) {
        [currentEditingTextField endEditing:YES];
        currentEditingTextField = NULL;
    }
}


// Override this in your subclass to handle eventual values that may prevent validation.

-(BOOL)textFieldValueIsValid:(UITextField*)textField
{
    return YES;
}

@end
  • Dengan mensubklasifikasikan formulir dan mengganti textFieldValueIsValid:metode, Anda dapat menghindari akhir edisi jika nilainya tidak benar untuk bidang yang diberikan.

  • Jika bidang memiliki delegasi yang diatur di Interface Builder, maka formulir tidak mengubahnya. Saya tidak melihat banyak alasan untuk mengatur delegasi yang berbeda ke bidang tertentu, tetapi mengapa tidak ...

Ada banyak cara untuk meningkatkan kelas tampilan formulir ini - Melampirkan delegasi, melakukan beberapa tata letak, menangani ketika keyboard mencakup bidang (menggunakan frameEditingTextField saat ini), secara otomatis mulai edisi untuk bidang berikutnya, ...

Saya pribadi menyimpannya dalam kerangka kerja saya, dan selalu mensubklasifikasikannya untuk menambahkan fitur, ini sering kali berguna "apa adanya".

Saya harap ini akan membantu. Ceria semua


1
Kelas yang membantu. Satu poin kecil, Anda tidak harus mengawali kelas Anda sendiri dengan "UI". Di objektif-c Anda harus menggunakan awalan Anda sendiri ("TL"?), Di Swift, jangan gunakan apa pun.
kubi

Terima kasih @ki. Betul sekali. Ini adalah MF dalam kerangka saya, seperti MooseFactory;)
Moose

1

jika Anda ingin semua pengeditan dalam UIViewController dapat Anda gunakan.

[[self view]endEditing:YES];

dan jika Anda ingin mengabaikan menyembunyikan keyboard UITextField pertanda kemudian gunakan.

1. Tambahkan delegasi di viewcontroller.h Anda

<UITextFieldDelegate>
  1. membuat delegasi tidak dapat ke bidang teks Anda.

    self.yourTextField.delegate = diri;

  2. tambahkan metode ini ke viewcontroller Anda.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; kembalikan YA;}


1

Secara terprogram mengatur delegasi dari UITextField dengan cepat 3

Terapkan UITextFieldDelegate di file ViewController.Swift Anda (mis. Kelas ViewController: UIViewController, UITextFieldDelegate {)

 lazy var firstNameTF: UITextField = {

    let firstname = UITextField()
    firstname.placeholder = "FirstName"
    firstname.frame = CGRect(x:38, y: 100, width: 244, height: 30)
    firstname.textAlignment = .center
    firstname.borderStyle = UITextBorderStyle.roundedRect
    firstname.keyboardType = UIKeyboardType.default
    firstname.delegate = self
    return firstname
}()

lazy var lastNameTF: UITextField = {

    let lastname = UITextField()
    lastname.placeholder = "LastName"
    lastname.frame = CGRect(x:38, y: 150, width: 244, height: 30)
    lastname.textAlignment = .center
    lastname.borderStyle = UITextBorderStyle.roundedRect
    lastname.keyboardType = UIKeyboardType.default
    lastname.delegate = self
    return lastname
}()

lazy var emailIdTF: UITextField = {

    let emailid = UITextField()
    emailid.placeholder = "EmailId"
    emailid.frame = CGRect(x:38, y: 200, width: 244, height: 30)
    emailid.textAlignment = .center
    emailid.borderStyle = UITextBorderStyle.roundedRect
    emailid.keyboardType = UIKeyboardType.default
    emailid.delegate = self
    return emailid
}()

// Tandai: - menangani delegasi textField ..

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

func textFieldShouldReturn(_ textField: UITextField) -> Bool {

    if textField == firstNameTF {

        lastNameTF.becomeFirstResponder()
    }

    else if textField == lastNameTF {

        emailIdTF.becomeFirstResponder()
    }
    else {
        view.emailIdTF(true)
    }
    return true
}

0

Buat fungsi hidekeyboard dan tautkan ke bidang teks dalam file .xib dan pilih DidEndOnExit

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Jika Anda telah membuat tampilan menggunakan Interface Builder, Gunakan yang berikut ini Cukup buat metode,

-(IBAction)dismissKeyboard:(id)sender
{
[sender resignFirstResponder];
}

Cukup klik kanan bidang teks dalam tampilan, dan atur acara sebagai Did End on Exit, dan kirimkan ke metode "dismissKeyboard".

Panduan terbaik untuk pemula adalah "Head First iPhone dan iPad Development, 2nd Edition"


0

coba ini

- (BOOL) textView: (UITextView*) textView shouldChangeTextInRange: (NSRange) range replacementText: (NSString*) text
{
    if ([text isEqualToString:@"\n"]) {
        [textView resignFirstResponder];
        return NO;
    }
    return YES;
}

0
//====================================================
//                  textFieldShouldReturn:
//====================================================
-(BOOL) textFieldShouldReturn:(UITextField*) textField { 
    [textField resignFirstResponder];
    if(textField.returnKeyType != UIReturnKeyDone){
        [[textField.superview viewWithTag: self.nextTextField] becomeFirstResponder];
    }
    return YES;
}

0

Siapa pun yang mencari Swift 3

1) Pastikan Delegate UITextField Anda terhubung ke ViewController Anda di Storyboard

2) Implementasikan UITextFieldDelegate di file ViewController.Swift Anda (mis. Kelas ViewController: UIViewController, UITextFieldDelegate {)

3) Gunakan metode delegasi di bawah ini

func textFieldShouldReturn(textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
return false }

0

Ini adalah bagaimana saya mengabaikan keyboard di Swift 4.2 dan berfungsi untuk saya:

    override func viewDidLoad() {
    super.viewDidLoad()

    let tap = UITapGestureRecognizer(target: self, action: 
    #selector(dismissKeyboard))

    view.addGestureRecognizer(tap)
    }

    @objc func dismissKeyboard (_ sender: UITapGestureRecognizer) {
    numberField.resignFirstResponder()
    }

-2

Swift 3, iOS 9+

@IBAction private func noteFieldDidEndOnExit(_ sender: UITextField) {}

UPD: Ini masih berfungsi dengan baik untuk saya. Saya pikir pria yang mengabdikan jawaban ini hanya tidak mengerti bahwa ia perlu mengikat tindakan ini ke UITextField di storyboard.


Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.