Як додати кнопку "Готово" на клавіатуру numpad в iOS


84

Отже, за замовчуванням клавіатура numpad не має кнопки „Готово“ або „Далі“, тому я хотів би додати її. У iOS 6 та нижче були деякі хитрощі, щоб додати кнопку на клавіатуру, але, здається, вони не працюють в iOS 7.

Спочатку я підписуюсь на клавіатуру, що відображає сповіщення

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

Потім я намагаюся додати кнопку, коли з’являється клавіатура:

- (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];
    }
}

Але цикл for не працює, оскільки він не знаходить жодного підпрогляду. Будь-які пропозиції? Я не зміг знайти жодного рішення для iOS7, тож чи є інший спосіб, яким я повинен це робити?

Редагувати: Дякую за всі пропозиції щодо хлопців на панелях інструментів, але я волію би не йти цим шляхом, оскільки я досить бідний на просторі (і це якось негарно).


Спробували цей допис? neoos.ch/blog / ...
Аніл

@Anil Цей спосіб налаштування UIKeyboard заборонений яблуком.
βhargavḯ

Перевірте за допомогою UIKeyboardDidShowNotification.
Praveen Matanam


2
Я не дуже хочу додавати панель інструментів, я хочу поставити кнопку прямо на клавіатурі.
Джордж Маккіббін,

Відповіді:


26

Це простий спосіб проектування готової кнопки на цифровій клавіатурі iOS7. У наведеному нижче методі делегування UITextField додайте сповіщення про показ клавіатури.

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

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

Тепер реалізуйте метод, keyboardWillShowяк показано нижче. Тут нам потрібно подбати про iOS7.

- (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];
        }
    });
  }
}

Тепер додайте цей макрос у відповідний заголовок для виявлення SYSTEM_VERSION

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


1
Дякую, це те, що я хотів :) На жаль, якщо на екрані вже була клавіатура, а потім ви перейшли на поле, яке потребує клавіатури з цифровою клавіатурою, тоді keyBoardWillShow не викликається. Але спасибі, крок у правильному напрямку ха-ха.
Джордж Маккіббін,

SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO, чому б не NSFoundationVersionNumber> NSFoundationVersionNumber_iOS_6_0? І перевірити це, NSFoundationVersionNumber_iOS_5_0 краще
гово

dispatch_async - не найнадійніший метод злому клавіатури тут. :(
pronebird

7
в iOS8 ця кнопка зроблено не приховується, після вимкнення клавіатури.
Hemant Chittora

2
Ця відповідь, хоч і розумна, обов’язково зламалася.
SwiftArchitect

187

Набагато безпечнішим підходом є використання а UIToolBarз Doneкнопкою як inputAccessoryView.


Зразок коду:

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;

Ваш -doneClickedметод повинен виглядати так:

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

Зразок коду 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

Ваш -doneClickedметод повинен виглядати так:

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

Можливо, мені доведеться це зробити. Мені не дуже подобається, скільки місця займає.
Джордж Маккіббін,

3
@GeorgeMcKibbin: Пробіл тут не повинен бути проблемою, оскільки він займе цей простір лише під час набору тексту. Крім того, на мій погляд, такий підхід набагато кращий, ніж базікання з клавіатурою, яка зазвичай не подобається Apple.
Bhavin

Коли я це роблю, я отримую лише панель інструментів у нижній частині екрана, і клавіатура більше не відображається. Думки?
Кріс

чудова відповідь, лише один лакомий фрагмент, arrayWithObjects негласно застарілий на користь літералів: [NSArray arrayWithObjects: doneButton, nil] => @ [doneButton]
Остін,

1
з iOS 8.0 UIBarButtonItemStyleBorderedє застарілим використанням UIBarButtonItemStyleDoneабоUIBarButtonItemStylePlain
Назір

130

Ще простіший спосіб:

Swift 3.0 і вище :

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
}

Свіфт 2.3 і нижче :

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
}

Завдання 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;
}

РЕДАГУВАТИ:

Я створив корисну бібліотеку під назвою DCKit , яка вже має готову панель інструментів:

Готово на панелі інструментів над клавіатурою в iOS (з використанням бібліотеки DCKit)

Він також має багато інших цікавих функцій.


1
Мені здається, ви додали кнопку гнучкої панелі до відповіді Бхавіна від 1 року тому як нову відповідь, щоб я міг зрозуміти, чому хтось за це проголосував. Може, я щось тут також пропустив?
Mark McCorkle

2
Так, я не використовую initWithTitle:@"Done", я використовую initWithBarButtonSystemItem:UIBarButtonSystemItemDoneзамість цього. Це поверне стандартну кнопку панелі "Готово" від Apple. Більше того, це буде вже локалізовано
Андрій Гордєєв

3
Це слід додати як покращення (коментар) до раніше правильної відповіді IMO або очікувати зниження голосів. Нова відповідь повинна передбачати інший підхід до вихідного питання, а не вдосконалення існуючого питання. Тим не менше, дякую за вдосконалення. ;-)
Марк Маккоркл

4
Ні, я не думаю. Коментарі не повинні використовуватися для написання коду :)
Андрій Гордєєв

13

Просто спираючись на відповіді вище із версією Swift, оскільки мені довелося її перекласти:

   @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

Можна використовувати

myTextField.inputAccessoryView = _inputView;

подання додаткового входу - це вигляд, який завжди надходить на клавіатуру та відхиляється за допомогою [textfield resignFirstResponder]

розмістіть doneнад поданням введення та виконайте відмовупершим відповідачем текстових полів.



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]; 
}

Я реалізував вашу відповідь, дуже схожу на те, що мені потрібно робити. Дякую. Але кнопка не відображається як анімований об'єкт під час показу клавіатури.
Arpit B Parekh

1

Вам потрібно визначити, чи перебуваєте ви на телефоні чи iPad, оскільки iPad реалізує клавішу повернення на клавіатурі "номер"


Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.