Как добавить кнопку `` Готово '' на цифровую клавиатуру в iOS


84

Итак, цифровая клавиатура по умолчанию не оснащена кнопкой «Готово» или «Далее», поэтому я бы хотел ее добавить. В 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

@Anil Apple запрещает такой способ настройки UIKeyboard.
βhargavḯ

Проверьте с помощью UIKeyboardDidShowNotification.
Правин Матанам

попробуйте это github.com/simonbs/BSKeyboardControls
the1pawan

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 лучше
govo

dispatch_async - не самый надежный метод взлома клавиатуры. :(
pronebird 08

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
Назир

131

Еще более простой способ:

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
}

Swift 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 , в которой уже есть панель инструментов из коробки:

Панель инструментов Done над клавиатурой в iOS (с использованием библиотеки DCKit)

У него также есть много других интересных функций.


1
Мне кажется, вы добавили кнопку гибкой полосы в ответ Бхавина год назад в качестве нового ответа, чтобы я мог понять, почему кто-то проголосовал за него. Может я и здесь что-то упустил?
Марк МакКоркл

2
Да, не использую initWithTitle:@"Done", initWithBarButtonSystemItem:UIBarButtonSystemItemDoneа вместо этого использую . Это вернет стандартную кнопку панели Apple Done. Более того, он уже будет локализован
Андрей Гордеев

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поверх представления ввода и выполните resignfirst респондента текстовых полей.



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

Я реализовал ваш ответ, очень похожий на то, что мне нужно сделать. Благодарю. Но при отображении клавиатуры кнопка не появляется как анимированный объект.
Арпит Б Парех

1

Вам действительно нужно определить, используете ли вы телефон или iPad, поскольку iPad реализует клавишу возврата на «цифровой» клавиатуре.


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.