Bir UITextField düzenlerken klavyeyi nasıl kapatırsınız?


181

Klavyeyi devre dışı bırakmak istediğimde UITextField'ım ilk yanıtlayıcıyı istifa etmesini söylemem gerektiğini biliyorum, ancak kullanıcının klavyedeki "Bitti" tuşuna ne zaman bastığını bilmiyorum. İzleyebileceğim bir bildirim var mı?


2
[self.view endDüzenleme: EVET]; temas halinde başladı delege en iyi çözümdür
Zar E Ahmer

Yanıtlar:


351

Sınıfına delege UITextFieldkoydum ViewController.

Bu sınıfta bu yöntemi aşağıdaki gibi uyguladım:

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

Yukarıdaki örneğe bakın ... IntefaceBuilder'ı denetleyiciniz olarak kullandığınız şeyle ilgili eyleme yönlendirin ... kullanıcı metin giriş sistemini (her basışta) kapattığında bu çağrılacaktır ...
Jason Coco

2
Bunların her ikisi de işe yarayacaktır - kullanıcı Return ("Bitti") tuşuna bastığında metin alanı eylemini gönderir ve ayrıca delegate -textFieldShouldReturn: öğesini gönderir.
Noah Witherspoon

BTW - bu aynı zamanda bir UISearchBar için de çalışır. Örneğin, benim kod bir üye IBOutlet searchBarTusb vardı; 'Dönüş anahtarım' (UIReturnKeySearch) tıklandığında, - (void) searchBarSearchButtonClicked: ifadesini [searchBarTusb resignFirstResponder]; Ayrıca, 'dönüş anahtarı' NIB'de Arayüz Oluşturucu kullanılarak ayarlanmıştır.
mobibob

Neden NOyerine geri dönelim YES?
Iulian Onofrei

@IulianOnofrei Geri dönüş düğmesinin varsayılan davranışı bir satır geri dönüşü eklemek ve klavyeyi ekranda tutmaktır. Döndürerek NOmetne satır dönüşü eklemekten kaçınırsınız.
kubi

47

Metin alanının DidEndOnExit olayını InterfaceBuilder'daki bir eyleme (IBAction) bağlarsanız, kullanıcı klavyeyi kapattığında (dönüş tuşu ile) ve gönderen olayı başlatan UITextField için bir referans olur.

Örneğin:

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

Ardından, InterfaceBuilder'da, metin alanının DidEndOnExit olayını denetleyicinizdeki (veya kullanıcı arabirimindeki olayları bağlamak için ne kullanıyorsanız) bu eyleme bağlayın. Kullanıcı her metin girdiğinde ve metin alanını kapattığında, denetleyiciye bu mesaj gönderilir.


Çalışabilir gibi görünen tek olay, yalnızca UITextField ilk yanıtlayıcı durumunu istifa ettikten sonra gönderildiğini bildiren textFieldDidEndEditing'dir. İlk yanıtlayan durumunu ne zaman istifa etmem gerektiğini nasıl anlarım?
kubi

Terminoloji için özür dilerim ... bu gerçek bir bildirim (olay) değil ... Cevabımı hızlı bir örnek ve açıklama ile düzenleyeceğim, bu yüzden bakın :)
Jason Coco

1
Bu yanıtı açıklığa kavuşturmak için, return tuşuna bastığınızda textField "Çıkışta Sona Erdi" olayını gönderir, bu yüzden kontrolörünüze bağlamanız gerekir. Bu yöntemin yukarıda özetlediğim yöntemden daha kolay olduğunu düşünüyorum.
kubi

2
Bu cevabı düzenleyebilmeniz için HANGİ olaydan bahsedecek misiniz, lütfen? Bu delege ayarlamaktan çok daha güzel.
Dan Rosenstark

1
Bu cevabı oylamak istiyorsunuz, ancak DidEndOnExit olayından bahsetmeden önce yapamayız. Düzenleme ayrıcalıklarına sahip biri, OP'nin yapmaması durumunda lütfen değişiklik yapsın mı?
James Hart

32

Denetleyicinizde bir yöntem de oluşturabilirsiniz

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

ve ardından IB'deki Müfettiş'te Olay "Bittiğinde Çıkış Yapıldı" olayına bağlanır.


1
Bu neredeyse yanlış veya en azından noktayı kaçırıyor. DidEndOnExitEtkinliğe abone olarak, arama yapmanız gerekmez resignFirstResponder. Bunu sembolik bir kesme noktası koyarak test edebilirsiniz [UIResponder resignFirstResponder]. ResignFirstResponder çağırmasanız bile, yine de sistem tarafından çağrıldığını unutmayın. Bu Matt Neuburg'un
Chris Conover

19

Kubi, teşekkürler. Kodunuz işe yaradı. Sadece açık olmak için (gibi yeni başlayanlar için) UITextField's delegatemetin alanının bulunduğu ViewController eşit olacak şekilde ayarlamak zorunda. Bunu istediğiniz zaman yapabilirsiniz. viewDidLoadYöntemi seçtim .

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

Film şeridinize veya NIB'inize metin alanı eklediyseniz, metin alanını da orada ayarlayabilirsiniz delegate. Yukarıda gösterildiği gibi bunu programlı olarak yapmanız gerekmez. Her iki yaklaşım da işe yarar.
Rob

18

İşte hiç kod olmadan otomatik klavye işten çıkarma davranışını almak için bir hile. Uçta, Kimlik denetçisindeki İlk Yanıtlayıcı proxy nesnesini düzenleyerek yeni bir ilk yanıtlayıcı eylemi ekleyin; diyelim dummy:. Şimdi metin alanının Çıkışta Sona Erdi olayını dummy:İlk Yanıtlayıcı proxy nesnesinin eylemine bağlayın . Bu kadar! Metin alanının Çıkışta Sona Erdi olayı artık bir eylem-hedef çifti içerdiğinden, kullanıcı Return tuşuna dokunduğunda metin alanı klavyesini otomatik olarak kapatır; ve yanıtlayan zincirine gönderilen bir mesaj için bir işleyici bulamamaktan dolayı ceza olmadığından, hiçbir dummy:yerde uygulama olmamasına rağmen uygulama çökmez .


@matt Bir gevşeme sekmesi eklersem ve didEndOnExit olayını bağlarsam, o zaman gevşeme sekmesinin Return tuşuna basıldığında tetikleneceğini keşfettim. Olay bağlantısı olmadan segue tetiklenmez. Harika ama ha? Herhangi bir açıklama var mı? BTW: Swift (bitmiş) ve iOS10 (bölüm 6'da) kitaplarınız var. Bana çok yardımcı oldular!
Verticon

@Verticon soru ve cevap segues ile ilgisi yoktur, bu yüzden sorunu anlamıyorum ... :( bu tamamen klavye işten çıkarma hakkında
matt

@matt Üzgünüm, adamım. Ben piggy destek çünkü 1) nasıl UITextField'ın dönüş anahtarını ele ile uğraşırken bu iş parçacığı üzerine geldi; ve 2) sizinle etkileşim kurmak için bir şanstı (da kitaplar için teşekkürler). "Sorun" yok. Neden / nasıl çalıştığı konusunda benim tarafımdan anlayış eksikliği.
Verticon

@Verticon Yardım edemediğim için özür dilerim. Daha fazla bilgi ile yeni bir soru formüle etmekten çekinmeyin (demo projesi?) Ve yararlı olabilirsem beni çarp.
mat


11

Sadece ekle

[textField endEditing:YES];

klavyeyi devre dışı bırakmak ve seçici görünümünü görüntülemek istediğiniz yere.


10

Swift'te Denetleyiciye bir IBAction yazabilir ve metin alanının Çıkışta Sona Erdi olayını bu eyleme ayarlayabilirsiniz

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

5

Swift 4.2 ve% 100 çalışacak

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

Ayrıca kullanabilirsiniz

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

   [self.yourTextField resignFirstResponder];

  }

Çok sayıda Uitextfield'iniz varsa en iyisi:

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

2

İşte işe yaraması için yapmam gerekenlerdi ve bence bir klavye için bir Sayısal Tuş Takımı (ya da bitmiş düğmesi olmayan başkaları için) gerekli:

  1. ViewController UIView bir UIControl olarak değiştirdim.
  2. Adlı bir işlev oluşturdum

    -(IBAction)backgroundIsTapped:(id)sender

Bu, .h dosyasında da tanımlanmıştır.

Bundan sonra, Interface Builder'da ViewController için 'dokunma' bitine bağlandım.

'Arka plan dokunulur' işlevinde, ben koymak:

    [answerField resignFirstResponder];

'AnswerField' öğesini klavyeyi kaldırmak istediğiniz UITextField'ın adıyla değiştirmeyi unutmayın (açıkça UITextField öğenizin aşağıdaki gibi tanımlandığından emin olun :)

    IBOutlet UITextField * <nameoftextfieldhere>;

Bu konunun muhtemelen uzun zaman önce öldüğünü biliyorum ... ama bunun bir yerlerde birisine yardım edeceğini umuyorum!


.. ancak kullanıcı başka bir kontrole dokunursa çok iyi çalışmaz.
ragnarius

2

"TextFieldShouldReturn" yönteminin DONE tuşuna basan metin alanı nesnesini sağladığını göreceksiniz. ETİKET'i ayarlarsanız bu metin alanını açabilirsiniz. Veya nesnenin işaretçisini, yaratıcısı tarafından saklanan bazı üye değerleriyle izleyebilir ve karşılaştırabilirsiniz.

Bireysel çalışma için yaklaşımım şöyle:

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

    bool fDidResign = [textField resignFirstResponder];

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

    return fDidResign;
}

Bu arada istifa etmeyi reddeden "doğrulama" testini yaptım. Sadece gösterim içindir, bu nedenle kullanıcı NO yazıyorsa! sahaya girmezse, atmaz. Davranış istediğim gibiydi, ancak çıktı sırası beklediğim gibi değildi.

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

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

Bu reddi için NSLog çıktımı ve ardından kabulü aşağıdadır. İstifa sonucunu iade ettiğimi fark edeceksiniz, ancak arayan kişiye geri bildirmek için FALSE'i bana geri döndürmesini bekledim mi ?! Bunun dışında gerekli davranışa sahiptir.

13.313 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
13.320 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
13.327 ÇalışmaKbd [109: 207] HAYIR!
13.333 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: klavyeden istifa etti
59.891 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]
59.897 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldEndEditing:]
59.917 StudyKbd [109: 207] - [StudyKbdViewController doneEditText]: HAYIR
59.928 StudyKbd [109: 207] - [StudyKbdViewController textFieldShouldReturn:]: klavyeden istifa etti

1
u açıklayabilir miyim .. her iki durumda da HAYIR veya EVET döndürürsem aynı şeyler olur, bu nedenle textFieldShouldReturn delege yönteminde evet döndürme ihtiyacı
K. Jaiswal

1

Dönüş Anahtarı veya arka planda bir dokunuşla baskıyı sonlandırmanın oldukça temiz bir yolu.

Interface builder'da alanlarınızı sınıf UIFormView görünümüne gömün

Bu sınıf ne yapar:

  • Kendini otomatik olarak alan temsilcisi olarak ekleyin (Uçtan uyanmış veya elle eklenmiş)
  • Mevcut düzenlenmiş alanda referans tutma
  • Dönüşte klavyeyi kapatın veya arka planda dokunun

İşte kod:

Arayüz

#import <UIKit/UIKit.h>

@interface UIFormView : UIView<UITextFieldDelegate>

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

@end

uygulama

#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
  • Formu alt sınıflandırarak ve textFieldValueIsValid:yöntemi geçersiz kılarak , değer verilen alan için doğru değilse sürüm sonundan kaçınabilirsiniz.

  • Bir alanın Interface Builder'da ayarlanmış bir temsilcisi varsa, form alanı değiştirmez. Belirli bir alana farklı bir temsilci ayarlamak için pek çok neden göremiyorum, ama neden olmasın…

Bu form görünümü sınıfını iyileştirmenin birçok yolu vardır - Bir temsilci ekleyin, bazı düzenler yapın, klavyeler bir alanı kapladığında işlem yapın (currentEditingTextField çerçevesini kullanarak), sonraki alan için otomatik olarak sürümü başlat, ...

Şahsen bunu çerçevemde tutuyorum ve her zaman özellikler eklemek için alt sınıfta bırakıyorum, genellikle "olduğu gibi" kullanışlıdır.

Umarım yardımcı olur. Herkese şerefe


1
Yardımcı sınıf. Küçük bir nokta, kendi sınıflarınızın önüne "UI" eklememelisiniz. Objektif-c'de kendi ön ekinizi ("TL"?) Kullanmalısınız, Swift'te hiçbir şey kullanmayın.
Kubi

Teşekkürler @kubi. Doğru. Benim çerçevemde MF, MooseFactory gibi;)
Moose

1

bir UIViewController tüm düzenleme istiyorsanız kullanabilirsiniz.

[[self view]endEditing:YES];

Pertiküler bir UITextField klavye gizlemesini kapatmak istiyorsanız kullanın.

1. görünümünüze temsilci ekleyin.

<UITextFieldDelegate>
  1. yetkiyi metin alanınıza yapamaz hale getirin.

    self.yourTextField.delegate = self;

  2. bu yöntemi görünüm denetleyicinize ekleyin.

    - (BOOL) textFieldShouldEndEditing: (UITextField *) textField {[textField resignFirstResponder]; dönüş YES;}


1

Programlı olarak UITextField temsilcisini hızlıca ayarlayın 3

ViewController.Swift dosyanıza UITextFieldDelegate uygulayın (örn. Sınıf 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
}()

// İşaretle: - temsilci textField'i kullanma ..

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

Bir hidekeyboard işlevi oluşturun ve bunu .xib dosyasındaki metin alanına bağlayın ve DidEndOnExit'i seçin

-(IBAction)Hidekeyboard    
{    
      textfield_name.resignFirstResponder;    
}  

0

Görünümü Interface Builder'ı kullanarak oluşturduysanız, Aşağıdakileri kullanın Sadece bir yöntem oluşturun,

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

Görünümdeki metin alanını sağ tıklayın ve etkinliği Çıkışta Bitti olarak ayarlayın ve "dismissKeyboard" yöntemine bağlayın.

Yeni başlayanlar için en iyi rehber "İlk iPhone ve iPad Geliştirme, 2. Sürüm"


0

bunu dene

- (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

Swift 3 arayan herkes

1) UITextField Temsilcinizin Storyboard'daki ViewController'ınıza bağlı olduğundan emin olun

2) ViewController.Swift dosyanıza UITextFieldDelegate uygulayın (örn. Sınıf ViewController: UIViewController, UITextFieldDelegate {)

3) Aşağıdaki temsilci yöntemini kullanın

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

0

Swift 4.2'de klavyeyi bu şekilde kapatıyorum ve benim için çalışıyor:

    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: Benim için hala iyi çalışıyor. Bence bu cevabı adayan adam, bu eylemi hikaye tahtasındaki UITextField'e bağlaması gerektiğini anlamıyordu.


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.