İOS'ta sayısal tuş takımı klavyesine 'Bitti' düğmesi nasıl eklenir


84

Bu nedenle, sayısal tuş takımı klavyesi varsayılan olarak 'Bitti' veya 'İleri' düğmesiyle gelmez, bu yüzden bir tane eklemek istiyorum. İOS 6 ve altında, klavyeye bir düğme eklemek için bazı püf noktaları vardı, ancak iOS 7'de çalışmıyor gibi görünüyorlar.

Önce bildirimi gösteren klavyeye abone oluyorum

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

Sonra klavye göründüğünde bir düğme eklemeye çalışıyorum:

- (void)keyboardWillShow:(NSNotification *)note 
{
    // create custom button
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeSystem];
    doneButton.frame = CGRectMake(0, 50, 106, 53);
    doneButton.adjustsImageWhenHighlighted = NO;
    [doneButton setTitle:@"Done" forState:UIControlStateNormal];
    [doneButton addTarget:self action:@selector(dismissKeyboard) forControlEvents:UIControlEventTouchUpInside];

    // locate keyboard view
    UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
    UIView* keyboard;
    for(int i=0; i<[tempWindow.subviews count]; i++) 
    {
        keyboard = [tempWindow.subviews objectAtIndex:i];
        // keyboard view found; add the custom button to it
        if([[keyboard description] hasPrefix:@"UIKeyboard"] == YES)
        [keyboard addSubview:doneButton];
    }
}

Ancak for döngüsü herhangi bir alt görünüm bulamadığı için çalışmaz. Herhangi bir öneri? İOS7 için herhangi bir çözüm bulamadım, bu yüzden bunu yapmamın farklı bir yolu var mı?

Düzenleme: Araç çubukları için tüm önerileriniz için teşekkürler, ancak alan açısından fakir olduğum için (ve biraz çirkin) bu rotaya gitmeyi tercih etmiyorum.


Bu gönderiyi denediniz mi? neoos.ch/blog/…
Anil

@Anil UIKeyboard'un bu şekilde özelleştirilmesi apple tarafından yasaklanmıştır.
βhargavḯ

UIKeyboardDidShowNotification ile kontrol edin.
Praveen Matanam


2
Gerçekten bir araç çubuğu eklemek istemiyorum, düğmeyi doğrudan klavyenin üzerine koymak istiyorum.
George McKibbin

Yanıtlar:


26

Bu, iOS7 sayısal tuş takımında tamamlanmış bir düğmeyi yansıtmanın basit bir yoludur. Aşağıdaki UITextField temsilci yönteminde, klavye gösterisi için bir bildirim ekleyin.

-(void)textFieldDidBeginEditing:(UITextField *)textField {

[[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];
}

Şimdi yöntemi keyboardWillShowaşağıdaki gibi uygulayın. Burada iOS7 için ekstra özen göstermemiz gerekiyor.

- (void)keyboardWillShow:(NSNotification *)note {
// create custom button
UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
doneButton.frame = CGRectMake(0, 163, 106, 53);
doneButton.adjustsImageWhenHighlighted = NO;
[doneButton setImage:[UIImage imageNamed:@"doneButtonNormal.png"] forState:UIControlStateNormal];
[doneButton setImage:[UIImage imageNamed:@"doneButtonPressed.png"] forState:UIControlStateHighlighted];
[doneButton addTarget:self action:@selector(doneButton:) forControlEvents:UIControlEventTouchUpInside];

if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"7.0")) {
    dispatch_async(dispatch_get_main_queue(), ^{
        UIView *keyboardView = [[[[[UIApplication sharedApplication] windows] lastObject] subviews] firstObject];
        [doneButton setFrame:CGRectMake(0, keyboardView.frame.size.height - 53, 106, 53)];
        [keyboardView addSubview:doneButton];
        [keyboardView bringSubviewToFront:doneButton];

        [UIView animateWithDuration:[[note.userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]-.02
                              delay:.0
                            options:[[note.userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]
                         animations:^{
                             self.view.frame = CGRectOffset(self.view.frame, 0, 0);
                         } completion:nil];
    });
}else {
    // locate keyboard view
    dispatch_async(dispatch_get_main_queue(), ^{
        UIWindow* tempWindow = [[[UIApplication sharedApplication] windows] objectAtIndex:1];
        UIView* keyboard;
        for(int i=0; i<[tempWindow.subviews count]; i++) {
            keyboard = [tempWindow.subviews objectAtIndex:i];
            // keyboard view found; add the custom button to it
            if([[keyboard description] hasPrefix:@"UIKeyboard"] == YES)
                [keyboard addSubview:doneButton];
        }
    });
  }
}

Şimdi bu makroyu SYSTEM_VERSION’ı algılamak için uygun başlığa ekleyin

#define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:v options:NSNumericSearch] != NSOrderedAscending)


1
Teşekkürler, istediğim buydu :) Maalesef ekranda zaten bir klavye varsa ve daha sonra bir sayısal tuş takımı klavyesi gerektiren bir alana geçerseniz, keyBoardWillShow aranmaz. Ama teşekkürler, doğru yönde bir adım haha.
George McKibbin

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO neden NSFoundationVersionNumber> NSFoundationVersionNumber_iOS_6_0 olmasın? Ve test ediyorum, NSFoundationVersionNumber_iOS_5_0 daha iyi
govo

dispatch_async, burada klavyeye girmek için en güvenilir yöntem değildir. :(
pronebird

7
iOS8'de bu bitti düğmesi klavyenin kapatılmasından sonra gizlenmiyor.
Hemant Chittora

2
Bu cevap, akıllıca da olsa, kırılmaya mahkumdu.
SwiftArchitect

187

Çok daha güvenli bir yaklaşım kullanmaktır UIToolBarile Doneolarak Düğmesi inputAccessoryView.


Basit kod :

UIToolbar *keyboardDoneButtonView = [[UIToolbar alloc] init];
[keyboardDoneButtonView sizeToFit];
UIBarButtonItem *doneButton = [[UIBarButtonItem alloc] initWithTitle:@"Done"
                                                               style:UIBarButtonItemStyleBordered target:self
                                                              action:@selector(doneClicked:)];
[keyboardDoneButtonView setItems:[NSArray arrayWithObjects:doneButton, nil]];
txtField.inputAccessoryView = keyboardDoneButtonView;

Kişisel -doneClickedyöntem şu şekilde görünmelidir:

- (IBAction)doneClicked:(id)sender
{
    NSLog(@"Done Clicked.");
    [self.view endEditing:YES];
}

Örnek Kod Swift:

let keyboardDoneButtonView = UIToolbar.init()
keyboardDoneButtonView.sizeToFit()
let doneButton = UIBarButtonItem.init(barButtonSystemItem: UIBarButtonSystemItem.Done, 
                                                   target: self, 
                                                   action: Selector("doneClicked:")))    

keyboardDoneButtonView.items = [doneButton]
textFieldInput.inputAccessoryView = keyboardDoneButtonView

Kişisel -doneClickedyöntem şu şekilde görünmelidir:

func doneClicked(sender: AnyObject) {
  self.view.endEditing(true)
}

Bunu yapmak zorunda kalabilirim. Ne kadar yer kapladığını gerçekten sevmiyorum.
George McKibbin

3
@GeorgeMcKibbin: Burada mesele boşluk olmamalı çünkü bu alanı sadece siz yazarken alacaktır. Ayrıca, bana göre bu yaklaşım, genellikle Apple'ın sevmediği Klavye ile uğraşmaktan çok daha iyi.
Bhavin

Bunu yaptığımda, araç çubuğunu yalnızca ekranımın en altında görüyorum ve klavye artık görünmüyor. Düşünceler?
Chris

harika yanıt, sadece bir haber, arrayWithObjects, değişmez değerler lehine konuşulmadan kullanımdan kaldırıldı: [NSArray arrayWithObjects: doneButton, nil] => @ [doneButton]
Austin

1
iOS 8.0'dan UIBarButtonItemStyleBorderedkullanımdan kaldırıldı UIBarButtonItemStyleDoneveyaUIBarButtonItemStylePlain
Nazir

131

Daha da kolay yol:

Swift 3.0 ve üzeri :

func addDoneButton() {
    let keyboardToolbar = UIToolbar()
    keyboardToolbar.sizeToFit()
    let flexBarButton = UIBarButtonItem(barButtonSystemItem: .flexibleSpace,
        target: nil, action: nil)
    let doneBarButton = UIBarButtonItem(barButtonSystemItem: .done,
        target: view, action: #selector(UIView.endEditing(_:)))
    keyboardToolbar.items = [flexBarButton, doneBarButton]
    textField.inputAccessoryView = keyboardToolbar
}

Swift 2.3 ve altı :

func addDoneButton() {
    let keyboardToolbar = UIToolbar()
    keyboardToolbar.sizeToFit()
    let flexBarButton = UIBarButtonItem(barButtonSystemItem: .FlexibleSpace,
        target: nil, action: nil)
    let doneBarButton = UIBarButtonItem(barButtonSystemItem: .Done,
        target: view, action: #selector(UIView.endEditing(_:)))
    keyboardToolbar.items = [flexBarButton, doneBarButton]
    textField.inputAccessoryView = keyboardToolbar
}

Hedef C :

- (void)addDoneButton {
    UIToolbar* keyboardToolbar = [[UIToolbar alloc] init];
    [keyboardToolbar sizeToFit];
    UIBarButtonItem *flexBarButton = [[UIBarButtonItem alloc]
    initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace
    target:nil action:nil];
    UIBarButtonItem *doneBarButton = [[UIBarButtonItem alloc]
    initWithBarButtonSystemItem:UIBarButtonSystemItemDone
    target:self.view action:@selector(endEditing:)];
    keyboardToolbar.items = @[flexBarButton, doneBarButton];
    self.textField.inputAccessoryView = keyboardToolbar;
}

DÜZENLE:

Araç çubuğunu kutudan çıkaran DCKit adında kullanışlı bir kitaplık oluşturdum :

İOS'ta klavyenin üzerinde araç çubuğu tamamlandı (DCKit kitaplığı kullanılarak)

Ayrıca diğer birçok harika özelliğe sahiptir.


1
Bana öyle geliyor ki, Bhavin'in 1 yıl önceki cevabına yeni bir cevap olarak bir esnek çubuk düğmesi eklediniz, böylece birisinin neden reddettiğini anlayabiliyorum. Belki burada da bir şeyi kaçırdım?
Mark McCorkle

2
Evet kullanmıyorum initWithTitle:@"Done", initWithBarButtonSystemItem:UIBarButtonSystemItemDoneonun yerine kullanıyorum. Bu, standart Apple'ın Bitti çubuğu düğmesini döndürür. Dahası, zaten yerelleştirilmiş olacak
Andrey Gordeev

3
Bu, daha önce doğru olan IMO yanıtına bir iyileştirme (yorum) olarak eklenmelidir veya olumsuz oylar beklenmektedir. Yeni bir cevap, mevcut soruda bir iyileştirme değil, orijinal soruya farklı bir yaklaşım içermelidir. Yine de gelişim için teşekkürler. ;-)
Mark McCorkle

4
Hayır, sanmıyorum. Yorumların kod yazmak için kullanılmaması gerekiyor :)
Andrey Gordeev

13

Çevirmek zorunda kaldığım için Swift versiyonuyla ilgili yukarıdaki cevaplara dayanarak:

   @IBOutlet weak var numberTextField: UITextField!

    override func viewDidLoad() {
        addDoneButtonTo(numberTextField)
    }

    // MARK: Done for numberTextField

    private func addDoneButtonTo(textField: UITextField) {
        let flexBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FlexibleSpace, target: nil, action: nil)
        let doneBarButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Done, target: self, action: "didTapDone:")
        let keyboardToolbar = UIToolbar()
        keyboardToolbar.sizeToFit()
        keyboardToolbar.items = [flexBarButton, doneBarButton]
        textField.inputAccessoryView = keyboardToolbar
    }

    func didTapDone(sender: AnyObject?) {
        numberTextField.endEditing(true)
    }

3

Kullanabilirsiniz

myTextField.inputAccessoryView = _inputView;

giriş aksesuarı görünümü, her zaman klavyenin üzerinden gelen ve [textfield resignFirstResponder]

koymak donegiriş görünümü üzerinde ve textfields arasında resignfirst yanıtlayıcı gerçekleştirin.


2

Sadece kullan

yourTextField.inputAccessoryView

umarım yardım edersin


2
enter code here

1. register the controller to the notification

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    // Keyboard events
    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillShow:)
                                             name:UIKeyboardWillShowNotification
                                           object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                         selector:@selector(keyboardWillHide:)
                                             name:UIKeyboardWillHideNotification
                                           object:nil];
}

2. don't forget to remove the controller from the notification centre

-(void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    [self.view endEditing:YES];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

3. implement keyboard notification handlers

- (void)keyboardWillShow:(NSNotification *)notification {

// create custom button
    UIButton *doneButton = [UIButton buttonWithType:UIButtonTypeCustom];
    doneButton.frame = CGRectMake(0, 107, 106, 53);
    [doneButton setTitle:@"Done" forState:UIControlStateNormal];
    [doneButton addTarget:self  action:@selector(doneButton:)forControlEvents:UIControlEventTouchUpInside];

// save the reference to the button in order to use it in keyboardWillHide method
   self.donekeyBoardBtn = doneButton;

// to my mind no need to search for subviews
   UIWindow *windowContainigKeyboard = [[[UIApplication sharedApplication] windows]  lastObject];
   [windowContainigKeyboard addSubview:self.donekeyBoardBtn];
   self.donekeyBoardBtn.frame = CGRectMake(0., CGRectGetHeight(w.frame) -  CGRectGetHeight(self.donekeyBoardBtn.frame), CGRectGetWidth(self.donekeyBoardBtn.frame), CGRectGetHeight(self.donekeyBoardBtn.frame));
}

- (void)keyboardWillHide:(NSNotification *)notification {

    [self.donekeyBoardBtn removeFromSuperview];
}

4. implement done button action

- (void)doneButton:(id)sender{
   // add needed implementation
      [self.view endEditing:YES]; 
}

Cevabınızı yapmam gerekene çok benzer şekilde uyguladım. Teşekkürler. Ancak klavye gösterildiğinde düğme animasyonlu bir nesne olarak gelmez.
Arpit B Parekh

1

İPad, "sayı" tuş takımında bir dönüş tuşu uyguladığından, telefonda mı yoksa iPad'de mi olduğunuzu algılamanız gerekir


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.