Tutup keyboard dengan menyentuh latar belakang UITableView

105

Saya memiliki UITableViewdengan UITextFields sebagai sel. Saya ingin menutup keyboard saat latar belakang UITableViewdisentuh. Saya mencoba melakukan ini dengan membuat UIButtonukuran UITableViewdan menempatkannya di belakang UITableView. Satu-satunya masalah adalah UIButtonmenangkap semua sentuhan bahkan ketika sentuhan itu ada di UITableView. Apa yang saya lakukan salah?

Terima kasih!

Hua-Ying
sumber
Pertanyaan dan jawaban berulang: Q1 , Q2 , Q3 .
Yantao Xie
Ini adalah jawaban terbaik stackoverflow.com/a/12851794/1418457
onmyway133

Jawaban:

203

Hal ini mudah dilakukan dengan membuat objek UITapGestureRecognizer (secara default ini akan mendeteksi "isyarat" pada satu ketukan sehingga tidak diperlukan penyesuaian lebih lanjut), menentukan target / tindakan saat isyarat diaktifkan, lalu melampirkan objek pengenal isyarat ke tampilan tabel Anda.

Misalnya Mungkin dalam viewDidLoadmetode Anda :

UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
[self.tableView addGestureRecognizer:gestureRecognizer];

Dan hideKeyboardmetodenya mungkin terlihat seperti ini:

- (void) hideKeyboard {
    [textField1 resignFirstResponder];
    [textField2 resignFirstResponder];
    ...
    ...
}

Perhatikan bahwa gerakan tidak ditembakkan saat menyentuh di dalam suatu UITextFieldobjek. Itu diaktifkan meskipun di UITableViewlatar belakang, tampilan footer, tampilan header dan di UILabelsdalam sel dll.

mixja
sumber
4
Ketika saya mencoba ini, saya menemukan itu mencegah tabel memilih sel :(. Solusi yang luar biasa sebaliknya
Brian
109
Sebagai solusi di bawah menunjukkan Anda dapat membuat ini bekerja jauh lebih baik dengan menetapkan:gestureRecognizer.cancelsTouchesInView = NO;
Zebs
3
Dan jangan lupa untuk melepaskan gestureRecognizer setelah terpasang ke tableView.
Paul Lynch
39
Untuk hideKeyboardmetodenya, alih-alih berkomunikasi langsung dengan kolom teks yang bisa Anda lakukan [self.view endEditing:NO];. Dari dokumen Apple: " Metode ini melihat tampilan saat ini dan hierarki subview untuk bidang teks yang saat ini menjadi responden pertama. Jika menemukannya, metode ini akan meminta bidang teks tersebut untuk mengundurkan diri sebagai responden pertama. Jika parameter gaya disetel ke YA, bidang teks bahkan tidak pernah diminta; itu dipaksa untuk mengundurkan diri. "
Gobot
1
menggunakan cara ini metode "didSelectRowAtIndexPath" saya tidak dipanggil. ada solusi untuk ini ??
uniruddh
127

Solusi UITapGestureRecognizer berfungsi dengan pemilihan sel tabel jika Anda menyetel:

gestureRecognizer.cancelsTouchesInView = NO;
Azbuky
sumber
1
Hal ini memungkinkan untuk menyentuh sel, tetapi isyaratnya dikenali juga, mungkin kita harus menerapkan metode delegasi inishouldReceiveTouch
onmyway133
61

Inilah cara terbaik untuk melakukannya. Lakukan saja ini

[self.view endEditing:YES];

atau

[[self.tableView superView] endEditing:YES];
Saad
sumber
di mana saya harus meletakkan kode ini? maaf saya pemula Dan berikan kode cepat.
Yohanes
54

Anda juga dapat melakukannya dari Storyboard: masukkan deskripsi gambar di sini

Ben
sumber
1
Apa pun yang saya pilih: Singkirkan saat menyeret, Singkirkan secara interaktif, ketika saya menyentuh sel tabel, itu dipilih. Saya menggunakan Xcode 8, swift 3. tolong bantu
John
22

Seperti UITableViewsubkelas dari UIScrollView, mengimplementasikan satu metode delegasi di bawah ini memberikan solusi yang sangat mudah dan cepat. Bahkan tidak perlu terlibat resignFirstResponderkarena hierarki tampilan melakukan introspeksi dan menemukan responden saat ini dan memintanya untuk mengundurkan diri dari status penjawabnya.

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}

Dan ingat untuk menambahkan UIScrollViewDelegateke file header.

Rajive Jain
sumber
2
Ini dapat dilakukan melalui satu liner ini seperti yang ditunjukkan oleh @Joe Masilotti jika Anda menargetkan iOS7 ke atas: self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;
atulkhatri
Apa yang terjadi jika Anda mengetuk bidang teks di bagian bawah layar yang seharusnya menggulir ke atas untuk menampilkan papan ketik? - Keyboard Anda akan disembunyikan.
Islam Q.
Swift 4 - self.tableView.keyboardDismissMode = UIScrollViewKeyboardDismissMode.onDrag
RobLabs
13

Pertama, dengarkan scrollViewWillBeginDraggingdi Anda UIViewControllerdengan menambahkan UIScrollViewDelegate:

Dalam file .h:

@interface MyViewController : UIViewController <UIScrollViewDelegate> 

Dalam file .m:

- (void)scrollViewWillBeginDragging:(UIScrollView *)activeScrollView {

    [self dismissKeyboard];

}

Kemudian dengarkan interaksi lainnya:

- (void)setupKeyboardDismissTaps {

    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UISwipeGestureRecognizer *swipeDownGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeDownGestureRecognizer.cancelsTouchesInView = NO;
    swipeDownGestureRecognizer.direction = UISwipeGestureRecognizerDirectionDown;
    [self.tableView addGestureRecognizer:swipeDownGestureRecognizer];

    UISwipeGestureRecognizer *swipeLeftGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeLeftGestureRecognizer.cancelsTouchesInView = NO;
    swipeLeftGestureRecognizer.direction = UISwipeGestureRecognizerDirectionLeft;
    [self.tableView addGestureRecognizer:swipeLeftGestureRecognizer];

    UISwipeGestureRecognizer *swipeRightGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    swipeRightGestureRecognizer.cancelsTouchesInView = NO;
    swipeRightGestureRecognizer.direction = UISwipeGestureRecognizerDirectionRight;
    [self.tableView addGestureRecognizer:swipeRightGestureRecognizer];


    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissKeyboard)];
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Kemudian terapkan dismissKeyboard :

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    [yourTextFieldPointer resignFirstResponder];

}

Dan jika, seperti saya, Anda ingin menutup keyboard untuk UITextField di dalam sel tabel kustom:

- (void)dismissKeyboard {

    NSLog(@"dismissKeyboard");

    CustomCellClass *customCell = [tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
    [customCell.textFieldInCell resignFirstResponder]; 

}

Semoga bisa membantu siapa pun yang mencari !!

bbeckford.dll
sumber
12
tableView.keyboardDismissMode = .onDrag
Dom Bryan
sumber
sedang mencari itu: D
Tobias
8

Inilah versi cepat untuk kesenangan pengkodean Anda:

Ia menambahkan pengenal gerakan tap lalu menutup keyboard. Tidak ada outlet untuk TextField diperlukan!

override func viewDidLoad() {
    super.viewDidLoad()
    view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: "handleTap:"))
}

func handleTap(sender: UITapGestureRecognizer) {
    if sender.state == .Ended {
        view.endEditing(true)
    }
    sender.cancelsTouchesInView = false
}
Biodave
sumber
1
Ini bekerja bahkan dengan tableViewCell kustom! Saya telah menghabiskan begitu banyak waktu untuk mencoba memikirkan hal ini. Terima kasih banyak! Kamu adalah pahlawanku. youtu.be/EqWRaAF6_WY
peacetype
8

Ada versi Swift 3 tanpa memblokir ketukan pada sel.

Dalam viewDidLoad()metode:

let dismissKeyboardGesture = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
dismissKeyboardGesture.cancelsTouchesInView = false
tableView.addGestureRecognizer(dismissKeyboardGesture)

Dan hideKeyboardterlihat seperti ini:

func hideKeyboard() {
    view.endEditing(true)
}
Ivan Smetanin
sumber
7

Saya melakukannya seperti ini:

Buat metode di TableViewController Anda untuk menonaktifkan responden pertama (yang akan menjadi TextBox Anda pada saat itu)

- (BOOL)findAndResignFirstResonder:(UIView *)stView {
    if (stView.isFirstResponder) {
        [stView resignFirstResponder];
        return YES;     
    }

    for (UIView *subView in stView.subviews) {
        if ([self findAndResignFirstResonder:subView]) {
            return YES;
        }
    }
    return NO;
}

Dalam tableView:didSelectRowAtIndexPath:memanggil metode sebelumnya:

- (void)tableView:(UITableView *)tableView
                             didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    ...
    [self findAndResignFirstResonder: self.view];
    ...
}
sha
sumber
Anda salah melakukannya seperti yang Anda minta. Anda tidak meletakkan tombol pada tampilan Anda memberi tahu tampilan untuk melepaskan keyboard seperti jawaban ini mengatakan
2
Ini berfungsi dengan baik jika Anda mengetuk dalam sel tampilan tabel (dan di luar bidang UIText apa pun dalam sel tampilan tabel itu). Namun, jika saya mengetuk latar belakang tampilan tabel (yang seringkali merupakan target yang lebih mudah didapat di - Hukum yay Fitts!), Tidak beruntung. Benar, itu yang diharapkan, karena kita melakukan operasi ini dalam tableView: didSelectRowAtIndexPath :. Jika ini dapat disesuaikan entah bagaimana untuk bekerja dengan mengetuk di tempat lain dalam tampilan tabel (yang tidak menginginkan fokus keyboard), saya pikir kita punya pemenang di sini!
Joe D'Andrea
Saya memiliki masalah yang sama dengan jdandrea. Itu didSelectRowAtIndexPathtidak akan menyala jika Anda mengetuk TableView itu sendiri.
zekel
jika didSelectRowAtIndexPath tidak cukup, lakukan hal yang sama di touchesBegan juga!
Amogh Talpallikar
5

Saya memiliki UITableViewControllerdan penerapan touchesBegan:withEvent:tidak berhasil untuk saya.

Inilah yang berhasil:

Cepat:

override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
    view.endEditing(true)
}

Objective-C:

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
    [self.view endEditing:YES];
}
MontiRabbit
sumber
Ide bagus, saya menyukainya.
HotFudgeSunday
4
@interface DismissableUITableView : UITableView {
}
@end

@implementation DismissableUITableView

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

@end

Kemudian pastikan bahwa dalam file NIB Anda, Anda menetapkan jenis UITableView Anda ke DismissableUITableView ..... mungkin saya bisa memikirkan nama yang lebih baik untuk kelas ini, tetapi Anda mengerti maksudnya.

bandejapaisa
sumber
4

Jika Anda menargetkan iOS7, Anda dapat menggunakan salah satu dari berikut ini:

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeOnDrag;

tableView.keyboardDismissMode = UIScrollViewKeyboardDismissModeInteractive;

Yang pertama akan menganimasikan keyboard dari layar ketika tampilan tabel digulir dan yang kemudian akan menyembunyikan keyboard seperti aplikasi Pesan stok.

Perhatikan bahwa ini dari UIScrollView, yang UITableViewdiwarisi dari.

Joe Masilotti
sumber
bagus. Saya mengatur untuk memilah-milahnya dengan menggesek layar dari atas ke atas hingga keyboard mulai bergerak ke bawah, lalu menggesek kembali hingga keyboard bergerak sedikit, lalu melepaskannya. scrollview tidak muncul kembali ke atas sebagaimana mestinya.
Sam
3

Coba ini:

viewDidLoad(){

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

    tableView.addGestureRecognizer(tap)

}
//Calls this function when the tap is recognized.
@objc func dismissKeyboard() {

    //Causes the view (or one of its embedded text fields) to resign the first responder status.
    view.endEditing(true)

}
Michael Colonna
sumber
2

UITableView adalah subclass dari UIScrollView.

Cara saya melakukannya adalah dengan mendengarkan acara gulir oleh pengguna dan kemudian resignFirstResponder. Berikut metode UIScrollViewDelegate untuk diterapkan dalam kode Anda;

- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView

Ketika mendekati masalah semacam ini, saya telah menemukan cara terbaik adalah dengan meneliti protokol delegasi untuk setiap objek dan kelas induk (dalam hal ini UITableViewDelegate, UIScrollViewDelegate. Jumlah peristiwa yang diaktifkan objek NS cukup besar dan komprehensif. Ini juga lebih mudah menerapkan protokol kemudian mensubkelas apapun.

pschang
sumber
2

Saya memiliki masalah yang sama dan inilah solusi saya, ini bekerja dengan sempurna untuk saya:

Dalam tampilan atau pengontrol tampilan yang Anda terapkan <UITextFieldDelegate>

(Dalam kasus saya, saya memiliki kebiasaan UITableViewCell disebut TextFieldCell),

Nyatakan UITapGestureRecognizersebagai properti:

@interface TextFieldCell : UITableViewCell <UITextFieldDelegate>
{
    UITextField *theTextField;
    UITapGestureRecognizer *gestureRecognizer;
}
@property (nonatomic,retain) UITextField *theTextField;
@property (nonatomic,retain) UITapGestureRecognizer *gestureRecognizer; 

Dan lakukan inisialisasi di tampilan / pengontrol Anda:

self.gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(closeKeyboard:)];

Dalam - (void)textFieldDidBeginEditing:(UITextField *)textFieldmetode ini, gunakan superViewuntuk naik ke tableView Anda dan panggil addGestureRecognizer:

[self.superview.superview addGestureRecognizer:gestureRecognizer];

Dan di - (void)textFieldDidEndEditing:(UITextField *)textField, hapus saja pengenal isyarat:

[self.superview.superview removeGestureRecognizer:gestureRecognizer];

Semoga membantu.

hac.jack
sumber
Ini berhasil untuk saya. Terima kasih hac.jack
gilsaints88
2

Saya ingin sel saya membuka keyboard ketika ada bagian dari sel yang dipilih dan menutupnya jika Anda mengklik di mana saja dari sel. Untuk membuka keyboard:

- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
    [super setSelected:selected animated:animated];
    if (selected)
    {
        [self.textField becomeFirstResponder];
    }
}

(CATATAN: Saya telah membuat subkelas sel tetapi Anda dapat dengan mudah mencapai ini dalam tableView:didSelectRowAtIndexPath:metode delegasiUITableView )

Melakukan ini berarti bahwa dengan solusi teratas jika Anda mengklik sel dua kali, keyboard akan berguncang karena, pertama pengenal gerakan mencoba menutup keyboard, dan kedua sel dipilih kembali dan mencoba membuka keyboard.

Solusinya adalah memeriksa apakah klik terjadi di dalam sel yang saat ini dipilih:

- (void)viewDidLoad
{
    [super viewDidLoad];
    //gesture recognizer to close the keyboard when user taps away
    UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard:)];
    tap.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tap];
}

-(void)dismissKeyboard:(UIGestureRecognizer*)tapGestureRecognizer
{
    if (!CGRectContainsPoint([self.tableView cellForRowAtIndexPath:[self.tableView indexPathForSelectedRow]].frame, [tapGestureRecognizer locationInView:self.tableView]))
    {
        [self.view endEditing:YES];
    }
}
Sam
sumber
2

Saya telah menemukan solusi yang bekerja dengan baik.

Diperlukan untuk menggunakan UIGestureRecognizerDelegate dan metode - gestureRecognizer: shouldReceiveTouch: .

Tambahkan pengenal gerakan ke TableView sebagai berikut:

UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
tapGestureRecognizer.cancelsTouchesInView = NO;
tapGestureRecognizer.delegate = self;
[self.suggestedTableView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];

Kemudian, implementasikan metode delegasi shouldReceiveTouch untuk menolak sentuhan yang dilakukan di kelas UITableViewCell. The hideKeyboard metode hanya akan dipanggil ketika disentuh telah dilakukan di luar kelas UITableViewCell.

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
    if([touch.view isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCell
    if([touch.view.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    // UITableViewCellContentView => UITableViewCellScrollView => UITableViewCell
    if([touch.view.superview.superview isKindOfClass:[UITableViewCell class]]) {
        return NO;
    }
    return YES; // handle the touch
}

- (void) hideKeyboard{
    [textField resignFirstResponder];
}
mlabraca.dll
sumber
2

UITableViewmemiliki backgroundViewproperti praktis , yang dengannya saya mencapai perilaku ini tanpa mengotak-atik pemilihan sel, seperti yang ditunjukkan di bawah ini di Swift:

let tableBackTapRecognizer = UITapGestureRecognizer(target: self, action: #selector(hideKeyboard))
tableView.backgroundView = UIView()
tableView.backgroundView?.addGestureRecognizer(tableBackTapRecognizer)
Şafak Gezer
sumber
1

Cukup menggunakan UITapGestureRecognizer dan cancelsTouchesInView = NOberarti mengetuk sel dan UITextView juga memicu persembunyian. Ini buruk jika Anda memiliki beberapa UITextView dan Anda mengetuk UITextView berikutnya. Keyboard akan mulai bersembunyi dan textView berikutnya menjadi firstResponder dan keyboard menjadi terlihat lagi. Untuk menghindarinya, periksa lokasi ketuk dan hanya sembunyikan keyboard jika ketuk tidak ada di sel:

// init
UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapTableView:)];
tapRecognizer.cancelsTouchesInView = NO;
[self.tableView addGestureRecognizer:tapRecognizer];


// Hide on tap
- (void)didTapTableView:(UITapGestureRecognizer *)tap
{
    CGPoint point = [tap locationInView:tap.view];
    [self.view endEditing:!CGRectContainsPoint([self.tableView rectForRowAtIndexPath:[self.tableView indexPathForRowAtPoint:point]], point)];
}

Agar scrollViewWillBeginDragging:dapat dipicu, scrollEnabledproperti tableView haruslahYES

// Hide on scroll
- (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self.view endEditing:YES];
}
Shawn Throop
sumber
Sempurna untukku. Menambahkan texbox ke sel tableview; jika saya menyentuh di luar tutup keyboard
Nicola
0

Mengapa Anda ingin membuat tabel yang penuh dengan bidang teks? Anda harus menggunakan tampilan rinci untuk setiap baris yang berisi bidang teks. Saat Anda mendorong tampilan mendetail, pastikan Anda memanggil "[myTextField intoFirstResponder]" sehingga pengguna dapat mulai mengedit hanya dengan satu klik dari daftar tabel.

Mugunth
sumber
Aplikasi Kontak Apple melakukan hal ini dengan tepat. Saya tidak akan mengatakan itu penuh dengan bidang teks, tetapi menggunakannya untuk efek yang baik.
Joe D'Andrea
2
Mengedit teks sebaris dalam tampilan tabel jauh lebih cepat dan lebih intuitif daripada mendorong tampilan detail untuk setiap bidang teks yang ingin diedit pengguna ... tanyakan saja formulir HTML terdekat, atau bidang teks di panel Preferensi iPhone, atau aplikasi Kontak, atau dll dll dll ... sungguh memalukan bahwa Apple belum menjadikan ini tipe sel standar, tetapi ada banyak info di web tentang mencapai ini.
glenc
0

Jika Anda ingin membuat subclass (ugh!) Tampilan tabel Anda, sesuatu seperti ini mungkin berhasil:

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

   BOOL backgroundTouched = YES;

   for (UITouch *touch in touches) {
      CGPoint location = [touch locationInView:self];
      for (UITableViewCell *cell in self.visibleCells) {
         if (CGRectContainsPoint(cell.frame, location)) {
            backgroundTouched = NO;
            break;
         }
      }
   }

   if (backgroundTouched) {
      for (UITableViewCell *cell in self.visibleCells) {
         // This presumes the first subview is the text field you want to resign.
         [[cell.contentView.subviews objectAtIndex:0] resignFirstResponder];
      }
   }

   [super touchesBegan:touches withEvent:event];
}
Joe D'Andrea
sumber
0

Jika Anda ingin menutup keyboard saat tombol kembali ditekan, Anda cukup menambahkan kode berikut di textField should return method yaitu:

- (BOOL)textFieldShouldReturn:(UITextField *)atextField
{
   [textField resignFirstresponder];
}

Beberapa bidang teks mungkin memiliki tampilan pemetik atau yang lain sebagai subview, jadi dalam hal ini metode di atas tidak berfungsi sehingga dalam hal ini kita perlu menggunakan kelas UITapGestureRecognizer, yaitu tambahkan cuplikan kode berikut ke metode viewDidLoad, yaitu:

UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                          action:@selector(dismissKeyboard)];

    [self.view addGestureRecognizer:tap];

Sekarang cukup tambahkan resign responder ke metode selector yaitu:

-(void)dismissKeyboard 
{
    [textField resignFirstResponder];
}

Semoga membantu, terima kasih :)

Eshwar Chaitanya
sumber
0

Banyak jawaban menarik. Saya ingin menyusun pendekatan yang berbeda ke dalam solusi yang menurut saya paling sesuai dengan skenario UITableView (ini yang biasanya saya gunakan): Yang biasanya kami inginkan pada dasarnya adalah menyembunyikan keyboard pada dua skenario: saat mengetuk di luar elemen Text UI, atau saat menggulir ke bawah / atas UITableView. Skenario pertama kita dapat dengan mudah menambahkan melalui TapGestureRecognizer, dan yang kedua melalui metode UIScrollViewDelegate scrollViewWillBeginDragging :. Urutan bisnis pertama, metode untuk menyembunyikan keyboard:

   /**
     *  Shortcut for resigning all responders and pull-back the keyboard
     */
    -(void)hideKeyboard
    {
        //this convenience method on UITableView sends a nested message to all subviews, and they resign responders if they have hold of the keyboard
        [self.tableView endEditing:YES];

    }

Metode ini mengembalikan UI bidang teks apa pun dari sub-tampilan dalam hierarki tampilan UITableView, jadi lebih praktis daripada mengundurkan diri setiap elemen secara independen.

Selanjutnya kami akan menangani pembubaran melalui gerakan Tap di luar, dengan:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    [self setupKeyboardDismissGestures];

}

- (void)setupKeyboardDismissGestures
{

//    Example for a swipe gesture recognizer. it was not set-up since we use scrollViewDelegate for dissmin-on-swiping, but it could be useful to keep in mind for views that do not inherit from UIScrollView
//    UISwipeGestureRecognizer *swipeUpGestureRecognizer = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
//    swipeUpGestureRecognizer.cancelsTouchesInView = NO;
//    swipeUpGestureRecognizer.direction = UISwipeGestureRecognizerDirectionUp;
//    [self.tableView addGestureRecognizer:swipeUpGestureRecognizer];

    UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(hideKeyboard)];
    //this prevents the gestureRecognizer to override other Taps, such as Cell Selection
    tapGestureRecognizer.cancelsTouchesInView = NO;
    [self.tableView addGestureRecognizer:tapGestureRecognizer];

}

Menyetel tapGestureRecognizer.cancelsTouchesInView ke NO adalah untuk menghindari gestureRecognizer menimpa cara kerja normal dalam UITableView (misalnya, tidak mengganggu Seleksi sel).

Terakhir, untuk menangani penyembunyian keyboard saat Menggulir ke atas / bawah UITableView, kita harus mengimplementasikan protokol UIScrollViewDelegate scrollViewWillBeginDragging: metode, sebagai:

file .h

@interface MyViewController : UIViewController <UIScrollViewDelegate>

file .m

#pragma mark - UIScrollViewDelegate

-(void)scrollViewWillBeginDragging:(UIScrollView *)scrollView
{
    [self hideKeyboard];
}

Saya harap ini membantu! =)

Robertibiris
sumber
0

Inilah cara saya akhirnya membuat karya. Saya menggabungkan saran dan kode dari jawaban yang berbeda. Fitur: menutup keyboard, memindahkan bidang teks di atas keyboard saat mengedit dan menyetel jenis kembali keyboard "Berikutnya" dan "Selesai". GANTI "..." dengan lebih banyak bidang

static const CGFloat ANIMATION_DURATION = 0.4;
static const CGFloat LITTLE_SPACE = 5;
CGFloat animatedDistance;
CGSize keyboardSize;

@interface ViewController () <UITextFieldDelegate>
 @property (weak, nonatomic) IBOutlet UITextField *firstNameTXT;
  .....// some other text fields
 @property (weak, nonatomic) IBOutlet UITextField *emailTXT;
@end

@implementation ViewController
- (void)viewDidLoad{
.....
// add tap gesture to help in dismissing keyboard
UITapGestureRecognizer * tapGesture = [[UITapGestureRecognizer alloc]
                                       initWithTarget:self
                                       action:@selector(tapScreen:)];// outside textfields

[self.view addGestureRecognizer:tapGesture];

// set text fields return key type to Next, last text field to Done
[self.firstNameTXT setReturnKeyType:UIReturnKeyNext];
.....
[self.emailTXT setReturnKeyType:UIReturnKeyDone];

// set text fields tags
[self.firstNameTXT setTag:0];
....// more text fields
[self.emailTXT setTag:5];

// add keyboard notification
[[NSNotificationCenter defaultCenter] addObserver:self     selector:@selector(keyboardDidShow:) name:UIKeyboardDidShowNotification object:nil];
}
[[NSNotificationCenter defaultCenter] addObserver:self      selector:@selector(keyboardDidHide:) name:UIKeyboardDidHideNotification object:nil];
}

// dismiss keyboard when tap outside text fields
- (IBAction)tapScreen:(UITapGestureRecognizer *)sender {
  if([self.firstNameTXT isFirstResponder])[self.firstNameTXT resignFirstResponder];
  ...
  if([self.emailTXT isFirstResponder])[self.emailTXT  resignFirstResponder];

  }
- (BOOL)textFieldShouldReturn:(UITextField *)textField{
   if(textField.returnKeyType==UIReturnKeyNext) {
     // find the text field with next tag
     UIView *next = [[textField superview] viewWithTag:textField.tag+1];
     [next becomeFirstResponder];
   } else if (textField.returnKeyType==UIReturnKeyDone || textField.returnKeyType==UIReturnKeyDefault) {
    [textField resignFirstResponder];
 }
return YES;
}

// Moving current text field above keyboard
-(BOOL) textFieldShouldBeginEditing:(UITextField*)textField{
   CGRect viewFrame = self.view.frame;
   CGRect textFieldRect = [self.view.window convertRect:textField.bounds fromView:textField];
   CGRect viewRect = [self.view.window convertRect:self.view.bounds fromView:self.view];
   CGFloat textFieldBottomLine = textFieldRect.origin.y + textFieldRect.size.height + LITTLE_SPACE;//

   CGFloat keyboardHeight = keyboardSize.height;

   BOOL isTextFieldHidden = textFieldBottomLine > (viewRect.size.height - keyboardHeight)? TRUE :FALSE;
  if (isTextFieldHidden) {
    animatedDistance = textFieldBottomLine - (viewRect.size.height - keyboardHeight) ;
    viewFrame.origin.y -= animatedDistance;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
  return YES;
}

-(void) restoreViewFrameOrigionYToZero{
  CGRect viewFrame = self.view.frame;
  if (viewFrame.origin.y != 0) {
    viewFrame.origin.y = 0;
    [UIView beginAnimations:nil context:NULL];
    [UIView setAnimationBeginsFromCurrentState:YES];
    [UIView setAnimationDuration:ANIMATION_DURATION];
    [self.view setFrame:viewFrame];
    [UIView commitAnimations];
  }
}

-(void)keyboardDidShow:(NSNotification*)aNotification{
   NSDictionary* info = [aNotification userInfo];
   keyboardSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;
 }

-(void)keyboardDidHide:(NSNotification*)aNotification{
   [self restoreViewFrameOrigionYToZero];// keyboard is dismissed, restore frame view to its  zero origin
}
@end
Kamel
sumber
0

@ Jawaban mixca sangat berguna tetapi bagaimana jika saya memiliki sesuatu yang berbeda dari UITextField. Saya pikir cara terbaik untuk menanganinya dengan mencari semua subview tampilan utama dengan fungsi rekursif, periksa contoh di bawah ini

- (BOOL)findAndResignFirstResponder {
if (self.isFirstResponder) {
    [self resignFirstResponder];
    return YES;
}

    for (UIView *subView in self.subviews) {
        if ([subView findAndResignFirstResponder]) {
            return YES;
        }
    }
    return NO;
}

dan juga Anda dapat meletakkan metode ini ke kelas utilitas Anda dan dapat menggunakan dari gerakan tap seperti jawaban @ mixca ..

mert
sumber
0

Cepat 4 / 4.2 / 5

Anda juga dapat menutup keyboard saat sel diketuk - sebelum melakukan hal lain.

    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    view.endEditing(true)
    // Do something here
    }
N. Der
sumber
0

tableView.keyboardDismissMode = .onDrag // .interactive

K. Mitra
sumber